java多线程 —— 两种实际应用场景模拟
最近做的偏向并发了,因为以后消息会众多,所以,jms等多个线程操作数据的时候,对共享变量,这些要很注意,以防止发生线程不安全的情况。
(一)
先说说第一个,模拟对信息的发送和接收。场景是这样的:
就像笔者之前做的消息的发送,一个是服务器,一个是客户端。发送的话,要保证信息100%的发送给客户端,那么发给客户端之后,客户端返回一个消息告诉服务器,已经收到。当服务器一直没有收到客户端返回的消息,那么服务器会一直发送这个信息,直到客户端发送回确认信息,这时候再删除重复发送的这个信息。
为了模拟这个场景,这里写两个线程,一个是发送,一个是接收,把发送的信息,要保存到线程安全的对象里面,防止发生线程安全问题,这里采用concurrenthashmap。
发送代码:
package com.TestThread;
/*
*
* @author 薛定饿的猫
*
* */
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap; public class PushThread extends Thread { @Override
public void run() {
// TODO Auto-generated method stub
try {
sleep(6000);
while(MainThread.pushmessage.size()>0){
//重发消息
for(Entry<Integer, String> hashMap:MainThread.pushmessage.entrySet()){
System.out.println("消息id:"+hashMap.getKey()+"未发送成功,在此重发:"+hashMap.getValue());
}
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
发送代码,是不断遍历内存对象councurrenthashmap,从中取出信息,不断的重发。其中MainThread.pushmessage是内存对象,在最后一段代码中有定义。
当确认接收到信息后,另外一个线程来删除内存对象。
删除的代码:
package com.TestThread; /*
*
* @author 薛定饿的猫
*
* */
import java.util.Map.Entry; public class RemoveThread extends Thread { @Override
public void run() {
// TODO Auto-generated method stub
try {
for (int i = 0; i < 10000; i++) {
sleep(2000);
for(Entry<Integer, String> map:MainThread.pushmessage.entrySet()){
if (map.getKey()==i) {
System.out.println("成功收到id为:"+map.getKey()+"返回的信息,删除该元素");
MainThread.pushmessage.remove(map.getKey());
}
}
System.out.println("内存对象中的元素数量为:"+MainThread.pushmessage.size());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
这里是来删除已收到的信息,然后从内存中删除,不再发送。
然后写一个主类入口:
package com.TestThread;
/*
*
* @author 薛定饿的猫
*
* */
import java.util.concurrent.ConcurrentHashMap; public class MainThread {
public static ConcurrentHashMap<Integer, String> pushmessage=new ConcurrentHashMap<Integer,String>();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
pushmessage.put(i, "该消息是id为"+i+"的消息");
}
Thread pushThread=new PushThread();
Thread remove=new RemoveThread();
pushThread.start();
remove.start();
for (int i = 10; i < 20; i++) {
pushmessage.put(i, "又一波到来,消息是id为"+i+"的消息");
}
}
}
这样两个线程可以轮流的进行各自的事情,并且不会造成数据安全的问题。用这种方式,再结合Androidpn的推送机制,会更加符合实际生产中的应用。
(二)多线程同步计数器
多线程同步计数器,按道理也是可以按照上面的方式来进行处理,定义一个像concurrenthashmap的变量。在java中,确实也有另外一种变量,原子变量Atomic,有AtomicLong,AtomicInteger,AtomicReference这些。
如果在多线程环境下要给一些值赋唯一id的话,这个时候,就要考虑这个id的安全性问题,也就是一致性的问题,不能重复。这里有两个实现的代码:
package com.test;
public class ThreadCount {
public static void main(String[] args) {
Thread[] threads=new Thread[10000];
for (int i = 0; i < 10000; i++) {
threads[i]=new AThread();
threads[i].start();
}
}
}
class AThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
@SuppressWarnings("unused")
Counter counter=new Counter();
System.out.println(Counter.calNum());
}
}
class Counter{
private static long num;
public Counter(){
synchronized (Counter.class) {
num++;
}
}
public static synchronized long calNum(){
return num;
}
}
这里创建了10000个线程,每个线程都来访问这个计数器,在构造方法中来进行值的递增。
在计数器中,有两次用到同步,很多人都说用同步,经常会对性能造成影响。于是,用第二种的原子变量,这个性能应该会更好。
代码:
package com.test;
import java.util.concurrent.atomic.AtomicLong;
public class ThreadCount {
public static void main(String[] args) {
Thread[] threads=new Thread[10000];
for (int i = 0; i < 10000; i++) {
threads[i]=new AThread();
threads[i].start();
}
}
}
class AThread extends Thread{
@Override
public void run() {
System.out.println(MyCounter.calNum());
}
}
class Counter{
private static long num;
public Counter(){
synchronized (Counter.class) {
num++;
}
}
public static synchronized long calNum(){
return num;
}
}
class MyCounter{
private static AtomicLong num=new AtomicLong();
public static synchronized long calNum(){
return num.incrementAndGet();
}
}
这样写的话,在调用这个计数器的时候,直接不需要再new一个MyCounter对象。
这样可以作为工具类,直接调用MyCounter的calNum方法。
java多线程 —— 两种实际应用场景模拟的更多相关文章
- Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...
- Java多线程--两种实现方式
进程概述: 在这之前,有必要了解一下什么是进程? 在一个操作系统中,每个独立的执行的程序都可称为一个进程,也就是"正在运行的程序".如图所示: 线程概述: 如上所述,每个运行的程序 ...
- JAVA - 多线程 两种方法的比较
一.继承Thread类 实现方法: (1).首先定义一个类去继承Thread父类,重写父类中的run()方法.在run()方法中加入具体的任务代码或处理逻辑.(2).直接创建一个ThreadDemo2 ...
- Java中两种实现多线程方式的对比分析
本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...
- Java中有两种实现多线程的方式以及两种方式之间的区别
看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. Java中有两种实现多线程的方式.一是直接继承Thre ...
- java中两种类型变量
Java中有两种类型的变量,一种是对象类型,另一种是基础类型(primitive type). 对象类型普遍采用引用的方式,比如 List a = new ArrayList(); List b = ...
- JAVA 中两种判断输入的是否是数字的方法__正则化_
JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...
- JavaScript 与 Java 是两种完全不同的语言,无论在概念还是设计上。
JavaScript 与 Java 是两种完全不同的语言,无论在概念还是设计上. Java(由 Sun 发明)是更复杂的编程语言. ECMA-262 是 JavaScript 标准的官方名称. Jav ...
- python 多线程两种实现方式,Python多线程下的_strptime问题,
python 多线程两种实现方式 原创 Linux操作系统 作者:杨奇龙 时间:2014-06-08 20:24:26 44021 0 目前python 提供了几种多线程实现方式 thread,t ...
随机推荐
- 引用mvvmlight dll ,操作command
前言 因为vs2010没有集成mvvmlight 所以想要使用mvvmlight的relaycomman需要引用dll 需要测试某个功能的时候,不能进行快带的集成 引用mvvmlight dll 如果 ...
- django MongoDB上传文件
django上传文件,查询到的资料都是用的django自己的models.Model类,去定义一个FileField类型的存储文件,并且在里面加一句upload_to,如下所示: 但是如果用mon ...
- Easyui-datagrid显示时间的格式化代码
{field: 'Time', title: '时间', formatter: function (value, row, index) { var date = new Date(value); v ...
- PAT L1-009 N个数求和(模拟分数加法)
本题的要求很简单,就是求N个数字的和.麻烦的是,这些数字是以有理数“分子/分母”的形式给出的,你输出的和也必须是有理数的形式. 输入格式: 输入第一行给出一个正整数N(<=100).随后一行按格 ...
- python版本安装
目的 本文目的在于,对于不熟悉Python的人,教你: 1. 从哪里找到 可以下载到 各种版本的 包括Python 2.x和Python 3.x的 最新版本的 Python. 高手请无视之. 2.以及 ...
- 最高频的K个单词 · Top K Frequent Words
[抄题]: 给一个单词列表,求出这个列表中出现频次最高的K个单词. [思维问题]: 以为已经放进pq里就不能改了.其实可以改,利用每次取出的都是顶上的最小值就行了.(性质) 不知道怎么处理k个之外的数 ...
- 【JDK1.8】JUC——ReentrantLock
一.前言 在之前的几篇中,我们回顾了锁框架中比较重要的几个类,他们为实现同步提供了基础支持,从现在开始到后面,就开始利用之前的几个类来进行各种锁的具体实现.今天来一起看下ReentrantLock,首 ...
- springmvc将处理后的数据通过get方法传给页面时,可能会出现乱码。下面对于get请求中文参数出现乱码提出解决办法。
对于get请求中文参数出现乱码解决办法有两个: 1.修改tomcat配置文件(tomcat--->conf--->server.xml)添加编码与工程编码一致,如下: <Connec ...
- [BAT]批处理脚本双击可运行,但在定时计划任务中无法执行(当前工作路径不对导致的)
一开始,红色部分我是用set AutoPath=%cd%,双击可执行,但是将这个批处理脚本放在定时任务中无法执行,后来发现在定时执行的时候,当前工作路径不是批处理脚本所在的路径,而是C:/Window ...
- Netty 零拷贝(三)Netty 对零拷贝的改进
Netty 零拷贝(三)Netty 对零拷贝的改进 Netty 系列目录 (https://www.cnblogs.com/binarylei/p/10117436.html) Netty 的&quo ...