我开始学习java,现在我正处于并发章节。在阅读了一些关于并发的内容后,我尝试了一个自己的例子。
public class Task implements Runnable{
public void run() {
while(!Thread.interrupted()) {
try {
System.out.println("task");
TimeUnit.SECONDS.sleep(2);
}catch (InterruptedException e) {
System.out.println("interrupted");
}
}
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Task());
TimeUnit.SECONDS.sleep(10);
exec.shutdownNow();
}
问题在于我希望看到以下输出:
task
task
task
task
task
interrupted
但在我得到这个之后,程序会继续打印,直到我关闭它为止 所以,我的问题是我做错了什么?为什么程序会继续打印?
答案 0 :(得分:7)
当您关闭执行程序时,它会尝试通过中断它们来停止其正在运行的任务。这会导致抛出InterruptedException,但您只是吞下它并继续。您应该在catch子句中返回,和/或通过调用Thread.currentThread.interrupt()
来重置线程的中断状态,这将重置中断状态并退出循环。
答案 1 :(得分:4)
你仍处于while循环中,在循环中添加一个中断或其他方式。
catch (InterruptedException e) {
System.out.println("interrupted");
break;
}
Java中的线程是一种合作活动,你被要求停止,但你需要礼貌地实际做到这一点。这允许线程时间在其消亡之前整理其事务。
正如Simon和Amir详细解释的那样,你的循环终止条件令人惊讶地不够。
答案 2 :(得分:4)
关于Java tutorials about concurrency中断的部分很好地解释了这个问题:
中断状态标志
使用中断实现中断机制 内部标志,称为中断状态。调用 Thread.interrupt设置此标志。线程检查中断时 通过调用静态方法Thread.interrupted,中断状态为 清除。非静态isInterrupted方法,由一个人使用 线程查询另一个的中断状态,不改变 中断状态标志。
按惯例,通过抛出一个退出的任何方法 InterruptedException在清除时会清除中断状态。但是, 始终可以立即设置中断状态 再次,由另一个线程调用中断。
因此,当你在循环中捕获InterruptedException时,中断的状态已经被重置,因此,下一次调用Thread.interrupted()将返回false,这反过来使while循环继续运行。要停止循环,您有以下选项:
break
退出循环return
退出整个方法ScheduledExecutorService
并从Runnable
答案 3 :(得分:1)
“除了尽力尝试停止处理主动执行任务之外没有任何保证。例如,典型的实现将通过Thread.interrupt()取消,因此如果任何任务屏蔽或无法响应中断,它们可能永远不会终止。“