Java 中关于 BlockingDeque 用法

2018-12-25 10:15:14 +08:00
 evanJa
生产环境,消费者代码中,使用 while(!Thread.interrupted()),while 循环中执行 take 操作,这样操作没有隐患吧?
2858 次点击
所在节点    Java
17 条回复
lst2008
2018-12-25 11:55:27 +08:00
妥妥的出事
evanJa
2018-12-25 12:40:04 +08:00
@lst2008 你这回复一点营养都没有啊
xiaoidea
2018-12-25 12:50:39 +08:00
我一般用一个 AtomicBoolean 来控制是否继续,然后用带 timeout 的 poll,while(AtomicBoolean.get()) {poll(timeout)}
SoloCompany
2018-12-25 13:20:44 +08:00
没有任何意义
阻塞位置是 take 语句
interrupt 抛出的是异常
while 判断语句根本捕获不了
还不如 while true 的逻辑清晰
evanJa
2018-12-25 14:15:33 +08:00
@xiaoidea 可能业务场景不一样,我这需要有消息就消费,没有就阻塞等待消息消费
evanJa
2018-12-25 14:22:27 +08:00
@SoloCompany 嗯,其实用 while(true)也是一样的
kanepan19
2018-12-25 14:47:48 +08:00
interrupted 会打断一些重要的操作,如数据库 update 或 insert

while(true){

Object object = waitQueue.poll(5000, TimeUnit.MILLISECONDS);

if (object == null && finished && waitQueue.isEmpty()) {
// 判断是否结束标准
break;
}

...


}
kanepan19
2018-12-25 14:50:44 +08:00
再看了下标题, 你的情况直接 take 就行,
我上面的伪代码是有个结束开关,结束不要用 interrupted
evanJa
2018-12-25 15:30:48 +08:00
@kanepan19 嗯,我这消费消息主要是网络操作,调其他服务
SilentHill
2018-12-25 16:45:17 +08:00
完全没有必要,Thread.interrupted()还会消除掉当前 thread 的 interrupt 标志位,

take 方法内部本身就在 await,如果外部进行 interrupt,那么能够响应并会抛出一个 interruptedException,所以在外部进行 catch,然后决定后续业务怎么处理就可以了。
dengtongcai
2018-12-25 16:49:33 +08:00
这块你判断中断是出于什么考虑
evanJa
2018-12-25 17:42:46 +08:00
@SilentHill @dengtongcai 这个线程是要一直阻塞等待消费消息的,其实本身判断 Thread.interrupted()没什么用,可以用 while(true)代替,我的意思的正常情况下,是否没有显示调用 interrupt 方法,那么这个线程就会一直等待消费消息,因为我只开了这一个线程做消费者( class EventProcessor extends Thread ) 我是想问下这种情况有什么隐患吗?
SilentHill
2018-12-25 17:49:25 +08:00
@evanJa 额,隐患大了去了,假如现在系统要关闭了,这个线程你准备怎么关?
如果使用 running 标志位的方式,你就需要考虑到 blockingdequeue 的 take 方法里面的 await 问题,这个你不主动在外面 interrupt 的话,是会一直阻塞的(除非你 jvm 强行关了)。
正确友好关闭线程的方式是使用 isRunning 之类的标志位,while 的条件就是 while(isRunning), 然后在 take 方法外面捕捉到 inerruptException 后根据业务场景决定是否需要退出线程,万万不可忽视这个异常什么都不做,有时候会导致这个线程一直无法退出。
leohuachao
2018-12-25 19:05:57 +08:00
可以把 interrupt 理解为线程自身用的一个标志位,表示线程自身的状态,不应该用于业务上的循环判断,应该使用自定义的 isRunning 标志位
MoHen9
2018-12-25 19:25:02 +08:00
总结一下楼上的,

1.建议使用 take(),take()方法会阻塞线程,直到有数据时才会再次执行,而且不占用 CPU 资源,还方便 interrupt。

2.使用 while( isRunning),方便平滑结束线程。

楼主这种方式其实一直占着 CPU,不够节约资源。
evanJa
2018-12-25 19:39:11 +08:00
@MoHen9 多谢总结
evanJa
2018-12-25 19:45:58 +08:00
@SilentHill 多谢回复,系统关闭了,进程就被杀掉了,这个线程自然就退出了。目的就是不关闭线程,让他一直执行 take 操作

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/520705

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX