线程中断
线程中断以后还能被重新拉起吗?
线程被中断后就会先处理中断异常,执行完中断异常后,在继续执行这个代码块中后续的代码。全部代码执行完成后,该任务就已经结束了,不会被再次拉起了。
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> threadRun = executorService.submit(() -> {
try {
Thread.sleep(2000);
// 一旦触发中断了,这个触发中断语句的后面的代码就不会执行了
System.out.println("Thread run");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Thread interrupted:处理中断异常");
}
System.out.println("处理完成中断异常后继续执行接下来的代码");
});
Thread.sleep(1000);
// 相当于是触发所有的任务中断
//executorService.shutdownNow();
// 触发线程池中单个任务的中断
threadRun.cancel(true);
System.out.println("Main run");
}
如果没有中断异常,也没有中断检测interrupted(),executorService.shutdownNow();是如何结束线程池中的线程的?
shutdownNow() 方法会采取的操作
- 尝试中断线程:
shutdownNow()会遍历线程池中的所有工作线程,并调用每个线程的interrupt()方法。- 这会设置线程的中断状态,但不会强制终止线程。线程需要自行检查其中断状态或响应中断异常来终止执行。
- 返回未执行的任务:
shutdownNow()方法会立即尝试停止所有正在执行的任务,并返回一个List<Runnable>列表,其中包含那些尚未开始执行的任务。
- 任务的处理:
- 调用者可以检查这个返回的列表,决定如何处理这些未执行的任务。例如,可以选择重新提交这些任务到另一个线程池,或者记录日志以便后续处理。
- 线程池的状态:
- 调用
shutdownNow()方法后,线程池将不再接受新的任务提交。 - 线程池的状态会立即变为
STOP,这意味着线程池将不再启动任何新的线程来执行任务。
- 调用
线程不响应中断的情况
- 如果线程的任务代码没有检查中断状态,也没有执行可能抛出
InterruptedException的操作,那么调用shutdownNow()后,该线程可能不会立即终止。 - 在这种情况下,线程会继续执行完当前任务,除非任务本身包含某种机制来检测中断或响应外部信号。
实际应用建议
设计可中断的任务
为了确保线程池中的线程能够响应
shutdownNow(),建议设计任务时考虑中断机制。例如,定期检查中断状态,或在可能阻塞的操作中捕获InterruptedException。
样例代码
public class LongTimeTaskExecutorInterrupt {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> threadRun = executorService.submit(() -> {
while(true) {
// 模拟执行任务
for (int i = 0; i < 100; i++) {
System.out.println("task run:" + i);
}
System.out.println("task run success");
try {
Thread.sleep(1);
// 一旦触发中断了,这个触发中断语句的后面的代码就不会执行了
System.out.println("Thread run");
} catch (InterruptedException e) {
System.out.println("Thread run 响应中断");
throw new RuntimeException(e);
}
System.out.println("处理完成中断异常后/正常执行完中断检查的代码后 继续执行接下来的代码");
}
});
Thread.sleep(1000);
// 相当于是触发所有的任务中断
executorService.shutdownNow();
System.out.println("Main run");
}
}
- 使用自定义线程池和策略:
- 如果需要更细粒度的控制,可以考虑使用自定义的
ThreadPoolExecutor,并在其中实现特定的中断和关闭策略。
- 如果需要更细粒度的控制,可以考虑使用自定义的
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果