博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java多线程发布订阅,多线程实现发布订阅升级版---遗留问题
阅读量:4507 次
发布时间:2019-06-08

本文共 2313 字,大约阅读时间需要 7 分钟。

昨天晚上遗留的两个问题

1.两个消费者消费消息都到100了,但是下图中的日志未打印出来

8c6ccfe61c28f95de1d8fbacdbcfe4fa.png

这个问题看代码

public classConsumerObjectOne implementsRunnable {

@Overridepublic voidrun() {

while(true) {

if(PudConThread.arrayBlockingQueue.size() > 0) {

if(PudConThread.hasConsumerTotal.get() >= PudConThread.total) {

System.out.println("消费者1--消费已达上限停止消费");return;}

/***获取最新的一条消息消费*/try{

//这个地方是关键

MessageVO messageVO = PudConThread.arrayBlockingQueue.take();System.out.println("消费者1消费消息"+ messageVO.toString());PudConThread.hasConsumerTotal.getAndAdd(1);} catch(InterruptedException e) {

e.printStackTrace();}

}

}

}

}

e36d04a5d3059925674d06f5f45e3423.png

ArrayBlockingQueue 里面的take(),当队列里面的长度为空时,会进入await 状态,所以两个消费线程在消费掉最后一条时,队列是空队列,take()阻塞不能进行下次循环,消费结束消息不能打印

将消费线程中的,消费消息代码和判断消费消息数量代码位置对调一下就可以了

public classConsumerObjectOne implementsRunnable {

@Overridepublic voidrun() {

while(true) {

if(PudConThread.arrayBlockingQueue.size() > 0) {

/***获取最新的一条消息消费*/try{

MessageVO messageVO = PudConThread.arrayBlockingQueue.take();System.out.println("消费者1消费消息"+ messageVO.toString());PudConThread.hasConsumerTotal.getAndAdd(1);} catch(InterruptedException e) {

e.printStackTrace();}

if(PudConThread.hasConsumerTotal.get() >= PudConThread.total) {

System.out.println("消费者1--消费已达上限停止消费");return;}

}

}

}

}

在运行结果如下

5a3cffd228415a56f6139f29ddf0140f.png

不对调位置也可以如下改造,将take()换成poll()

public classConsumerObjectOne implementsRunnable {

@Overridepublic voidrun() {

while(true) {

if(PudConThread.hasConsumerTotal.get() >= PudConThread.total) {

System.out.println("消费者1--消费已达上限停止消费");return;}

if(PudConThread.arrayBlockingQueue.size() > 0) {

/***获取最新的一条消息消费*/MessageVO messageVO = PudConThread.arrayBlockingQueue.poll();if(messageVO != null) {

System.out.println("消费者1消费消息"+ messageVO.toString());PudConThread.hasConsumerTotal.getAndAdd(1);}

}

}

}

}

7b00665042611446d9c37851ea7422af.png

第2个问题  序号我们用的是AtomicInteger但是每次都会出现两个为0的序号

ce782e346ac53a2e15628be3bd1f30d9.png

分析:每次出现两个为0的序号是,两个生产者在设置序号的时候用的是 AtomicInteger的 get() 方法这个只是返回当前最新值,所以两个生产者并发去get 获取到了初始值0

代码改造如下

public classProductObjectOne implementsRunnable {

@Overridepublic voidrun() {

while(true) {

if(PudConThread.hasProductTotal.get() >= PudConThread.total) {

System.out.println("产品已达上限,停止生产");return;}

MessageVO messageVO = newMessageVO(PudConThread.hasProductTotal.getAndAdd(1),UUID.randomUUID().toString(),"ProductObjectOne---this is pubsub test");try{

PudConThread.arrayBlockingQueue.put(messageVO);} catch(InterruptedException e) {

e.printStackTrace();}

}

}

}

运行结果如下,未出现重复的序号了

894acbfc0ec115903968c82cff5b83ba.png

214709f1557989f83e583dc601bfcf08.png

6576e849915c6458f3b877736f3e16fa.png

转载地址:http://vhats.baihongyu.com/

你可能感兴趣的文章
Mysql创建自动生成时间列方法
查看>>
12171131第一次作业
查看>>
argparse
查看>>
Pandas使用to_csv保存中文数据用Excel打开是乱码
查看>>
超大整数计算模拟算法
查看>>
<USACO07JAN>解决问题Problem Solvingの思路
查看>>
docker学习
查看>>
C#3.0入门系列(六)-之OrderBy操作
查看>>
10.25 AITalkUat部署
查看>>
枚举学习
查看>>
阅读《构建之法》第8,9,10章
查看>>
用户体验的重要性
查看>>
第八十一节,CSS3变形效果
查看>>
WordCount 分析
查看>>
项目需求分析答辩总结
查看>>
PostgreSQL 利用pg_upgrade升级版本
查看>>
Mybatis分页插件PageHelper简单使用
查看>>
同步互斥——理发师睡觉问题
查看>>
Python编写的ARP扫描工具
查看>>
github之克隆
查看>>