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

Java 中关于 BlockingDeque 用法

  •  
  •   evanJa · 59 天前 · 1225 次点击
    这是一个创建于 59 天前的主题,其中的信息可能已经有所发展或是发生改变。
    生产环境,消费者代码中,使用 while(!Thread.interrupted()),while 循环中执行 take 操作,这样操作没有隐患吧?
    17 回复  |  直到 2018-12-25 19:45:58 +08:00
        1
    lst2008   59 天前
    妥妥的出事
        2
    evanJa   59 天前
    @lst2008 你这回复一点营养都没有啊
        3
    xiaoidea   59 天前
    我一般用一个 AtomicBoolean 来控制是否继续,然后用带 timeout 的 poll,while(AtomicBoolean.get()) {poll(timeout)}
        4
    SoloCompany   59 天前 via iPhone
    没有任何意义
    阻塞位置是 take 语句
    interrupt 抛出的是异常
    while 判断语句根本捕获不了
    还不如 while true 的逻辑清晰
        5
    evanJa   59 天前
    @xiaoidea 可能业务场景不一样,我这需要有消息就消费,没有就阻塞等待消息消费
        6
    evanJa   59 天前
    @SoloCompany 嗯,其实用 while(true)也是一样的
        7
    kanepan19   59 天前
    interrupted 会打断一些重要的操作,如数据库 update 或 insert

    while(true){

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

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

    ...


    }
        8
    kanepan19   59 天前   ♥ 1
    再看了下标题, 你的情况直接 take 就行,
    我上面的伪代码是有个结束开关,结束不要用 interrupted
        9
    evanJa   59 天前
    @kanepan19 嗯,我这消费消息主要是网络操作,调其他服务
        10
    SilentHill   59 天前   ♥ 1
    完全没有必要,Thread.interrupted()还会消除掉当前 thread 的 interrupt 标志位,

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

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

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

    楼主这种方式其实一直占着 CPU,不够节约资源。
        16
    evanJa   59 天前
    @MoHen9 多谢总结
        17
    evanJa   59 天前
    @SilentHill 多谢回复,系统关闭了,进程就被杀掉了,这个线程自然就退出了。目的就是不关闭线程,让他一直执行 take 操作
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2273 人在线   最高记录 4385   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 21ms · UTC 12:29 · PVG 20:29 · LAX 04:29 · JFK 07:29
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1