美文网首页
记一个线程始终未按预期退出bug

记一个线程始终未按预期退出bug

作者: 凉风拂面秋挽月 | 来源:发表于2020-03-14 18:18 被阅读0次

    正如我在线程中断中所写的,interrupt标志是消耗品,且其本身无法中断线程。正是该问题导致我的项目中一个子线程未按照预期退出。

    问题描述

    主线程启动两个子线程A和B。B为ScheduledExecutorService的定时任务,通过shundown方法可终止该任务。A线程依赖于B的定时任务所得结果,故通过阻塞队列来实现A-B的顺序执行。
    主线程暴露出一个终止任务方法供使用者调用,B通过shundownNow方法终止,A通过interrupt设置中断标志,在A中死循环中通过isinterrupted方法判断跳出。

    while (true) {
    ......业务代码
    while(poll==null&&!Thread.currentThread().isInterrupted()) {
        poll = message.poll(5, TimeUnit.SECONDS);//尝试获取B线程的执行结果 
                    }
                    if(Thread.currentThread().isInterrupted()) {
                        System.out.println("完全跳出A");
                        break;
                    }
    ......业务代码
    }
    

    但在实际调用终止任务方法时,进程始终未退出,通过VisualVM监控虚拟机线程发现A线程在调用中断后并未退出。
    疑惑之下,在主线程中加入打印语句,发现A线程在B线程退出20s后依然处于alive状态,更令我感觉困惑的事情是在终止任务中添加interrupt中断标志后,添加了一条打印isInterrupted(),查看中断标志,结果居然是false。

    threadA.interrupt();
    System.out.println("A线程:"+threadA.isInterrupted());
    
    ...
    A线程:false
    ...
    

    bug修复

    正如我在线程中断的相关方法中所写的,interrupt标志是一个消耗品。在标志被sleep、wait响应后,标志位被重制为false。
    而阻塞队列的poll方法正是可以响应interrupt标志的方法

    E poll(long timeout, TimeUnit unit)
            throws InterruptedException;
    

    既然如此,设置中断的方式不能正确被响应到,那还是通过设置类成员属性标志位来解决问题吧。

    相关文章

      网友评论

          本文标题:记一个线程始终未按预期退出bug

          本文链接:https://www.haomeiwen.com/subject/kgpishtx.html