V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
evanJa
V2EX  ›  Java

Java 中关于 BlockingDeque 用法

  •  
  •   evanJa · 2018-12-25 10:15:14 +08:00 · 3006 次点击
    这是一个创建于 2162 天前的主题,其中的信息可能已经有所发展或是发生改变。
    生产环境,消费者代码中,使用 while(!Thread.interrupted()),while 循环中执行 take 操作,这样操作没有隐患吧?
    17 条回复    2018-12-25 19:45:58 +08:00
    lst2008
        1
    lst2008  
       2018-12-25 11:55:27 +08:00
    妥妥的出事
    evanJa
        2
    evanJa  
    OP
       2018-12-25 12:40:04 +08:00
    @lst2008 你这回复一点营养都没有啊
    xiaoidea
        3
    xiaoidea  
       2018-12-25 12:50:39 +08:00
    我一般用一个 AtomicBoolean 来控制是否继续,然后用带 timeout 的 poll,while(AtomicBoolean.get()) {poll(timeout)}
    SoloCompany
        4
    SoloCompany  
       2018-12-25 13:20:44 +08:00 via iPhone
    没有任何意义
    阻塞位置是 take 语句
    interrupt 抛出的是异常
    while 判断语句根本捕获不了
    还不如 while true 的逻辑清晰
    evanJa
        5
    evanJa  
    OP
       2018-12-25 14:15:33 +08:00
    @xiaoidea 可能业务场景不一样,我这需要有消息就消费,没有就阻塞等待消息消费
    evanJa
        6
    evanJa  
    OP
       2018-12-25 14:22:27 +08:00
    @SoloCompany 嗯,其实用 while(true)也是一样的
    kanepan19
        7
    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
        8
    kanepan19  
       2018-12-25 14:50:44 +08:00   ❤️ 1
    再看了下标题, 你的情况直接 take 就行,
    我上面的伪代码是有个结束开关,结束不要用 interrupted
    evanJa
        9
    evanJa  
    OP
       2018-12-25 15:30:48 +08:00
    @kanepan19 嗯,我这消费消息主要是网络操作,调其他服务
    SilentHill
        10
    SilentHill  
       2018-12-25 16:45:17 +08:00   ❤️ 1
    完全没有必要,Thread.interrupted()还会消除掉当前 thread 的 interrupt 标志位,

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

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

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

    楼主这种方式其实一直占着 CPU,不够节约资源。
    evanJa
        16
    evanJa  
    OP
       2018-12-25 19:39:11 +08:00
    @MoHen9 多谢总结
    evanJa
        17
    evanJa  
    OP
       2018-12-25 19:45:58 +08:00
    @SilentHill 多谢回复,系统关闭了,进程就被杀掉了,这个线程自然就退出了。目的就是不关闭线程,让他一直执行 take 操作
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1389 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:53 · PVG 07:53 · LAX 15:53 · JFK 18:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.