java线程中断异常处理仅在某些情况下停止执行进一步的代码

dojqjjoe  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(343)

下面的简短示例代码说明了我无法解释的行为

ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();

    Thread t = new Thread(() -> {
        long cnt = 0;
        try {
            while(!Thread.currentThread().isInterrupted()) {
                testQueue.add(Math.random());
                cnt++;
                try {
                    Thread.sleep(100);
                }catch (Exception e) {
                    System.out.println(String.format("inner interrupted inserted %d record", cnt));
                }
            }
        } catch (Exception e) {
            System.out.println(String.format("interrupted inserted %d record", cnt));
        }
        System.out.println(String.format("inserted %d record", cnt));
    });

如果我打电话 t.interrupt() 中断线程
预期的行为是2个打印行,表示:

inner interrupted inserted %d record
inserted %d record

其中%d替换为相应的值。
但实际结果是

inner interrupted inserted %d record

如果我们把线的内锁销去掉

ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();

    Thread t = new Thread(() -> {
        long cnt = 0;
        try {
            while(!Thread.currentThread().isInterrupted()) {
                testQueue.add(Math.random());
                cnt++;
                Thread.sleep(100);
            }
        } catch (Exception e) {
            System.out.println(String.format("interrupted inserted %d record", cnt));
        }
        System.out.println(String.format("inserted %d record", cnt));
    });

然后我们得到输出

interrupted inserted %d record
inserted %d record

正如预期的那样,外部catch正在捕获interruptexception
但是,如果我将break放在第一个代码示例的最内部catch中,如下所示:

ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();

    Thread t = new Thread(() -> {
        long cnt = 0;
        try {
            while(!Thread.currentThread().isInterrupted()) {
                testQueue.add(Math.random());
                cnt++;
                try {
                    Thread.sleep(100);
                }catch (Exception e) {
                    System.out.println(String.format("inner interrupted inserted %d record", cnt));
                    break; //this one
                }
            }
        } catch (Exception e) {
            System.out.println(String.format("interrupted inserted %d record", cnt));
        }
        System.out.println(String.format("inserted %d record", cnt));
    });

产生预期的行为。
为什么挡块的位置会产生这样的差异?

8yoxcaq7

8yoxcaq71#

有关详细信息,请参阅文档 Thread#interrupt :
如果此线程在调用[…]sleep(long)或sleep(long,int),[…]时被阻塞,那么它的中断状态将被清除,并且它将接收一个interruptedexception。
如果前面的条件都不成立,那么这个线程的中断状态将被设置。
也就是说在你的例子中 Thread#sleep 抛出异常xor Thread.currentThread().isInterrupted() 给你真实的感觉。
因此,在第一个示例中,您捕获了异常,执行print并在无限循环中输入/保持为 Thread.currentThread().isInterrupted() 总是 false .
在第二个示例中,try-catch没有嵌套在循环中,因此两个打印都会发生,线程也会按预期终止。
在第三个示例中,只需显式退出循环。
仅供参考:你不需要写作 System.out.println(String.format(...)) . 有 System.out.printf ,但别忘了 \n .

相关问题