首页 > 解决方案 > 为什么 shutdownNow() 方法能够在 Callable 对象中打破 for-loop,但在 Runnable 中却不能这样做,除非我们专门调用了 break?

问题描述

我有这个代码片段,它运行一个带有两个可调用或可运行类型任务的单线程执行程序。这两个任务都运行一个简单的 for 循环计数器,Thread.sleep()每次迭代都有延迟。第二个任务在第一个任务完成后立即开始。该awaitTermination()方法应该在执行程序完成之前关闭它。

我知道一旦时间过去就会shutdownNow()调用当前正在执行的任务,以某种方式设法立即打破第一个任务中的 for 循环,并在对象类型为 时中止第二个任务。现在,如果我将提交对象的类型更改为代码也将按预期终止 for 循环,但这只是因为我在调用.interrupt()awaitTermination()MyCallableTaskMyRunnableTaskbreakThread.sleep()

@Override public void run() {
    for (int j = 0; j < forLoops; j++) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            break;
        }
    }
}

如果没有中断,代码会先完成 for 循环然后停止。

我的问题是为什么我们不需要在call()实施中包含任何中断或返回MyCallableTask?我的意思是,代码如何在call()没有任何额外指令的情况下成功地立即打破方法中的 for 循环?

@Override public Void call() throws Exception {
    for (int j = 0; j < forLoops; j++) {
        Thread.sleep(sleepTime);
    }
    return null;
}

标签: javamultithreadingexecutorservice

解决方案


InterruptedException是一个检查异常。

您要么必须在方法内部处理它(使用 try/catch),要么声明该方法抛出它(或超类)。

可运行的实现不能抛出检查异常,例如InterruptedException(它的基本声明没有throws Exceptionor throws InterruptedException);Callable可以,因为它的声明可以。


顺便说一句,您的Runnable案例应该Thread.currentThread().interrupt()在中断之前调用,以便调用 Runnable 的任何东西也可以知道它被中断了。

您也不需要将 try/catch 放在循环周围而不是循环内部。


推荐阅读