java多线程发布订阅,多线程实现发布订阅升级版---遗留问题

昨天晚上遗留的两个问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值