Java 线程中断时,为什么线程池会中断其工作线程?
请看这个例子。我从我的生产项目中得到它。Web服务器接收命令并启动新线程,该线程通过ADPool启动计算。当用户想要结束计算时,他发送另一个命令来中断这个新线程,线程池的工作线程将关闭。它工作得很好,但我不明白为什么Java 线程中断时,为什么线程池会中断其工作线程?,java,multithreading,threadpool,Java,Multithreading,Threadpool,请看这个例子。我从我的生产项目中得到它。Web服务器接收命令并启动新线程,该线程通过ADPool启动计算。当用户想要结束计算时,他发送另一个命令来中断这个新线程,线程池的工作线程将关闭。它工作得很好,但我不明白为什么 public static void main(String[] args) throws Throwable { final ExecutorService p = Executors.newFixedThreadPool(2); System
public static void main(String[] args) throws Throwable {
final ExecutorService p = Executors.newFixedThreadPool(2);
System.out.println("main say: Hello, I'm Main!");
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " say: Starting monitor");
Thread monitor = new Thread(new Runnable() {
@Override
public void run() {
try {
while(true) {
Thread.sleep(1500);
System.out.println(Thread.currentThread().getName() + " say: I'm still here...hahahahah");
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " say: Bye for now!");
}
}
},"monitor");
monitor.setDaemon(true);
monitor.start();
List<Callable<Integer>> threads = new ArrayList<>();
for (int i = 0; i < 5; i++) {
threads.add(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + " say: Hello!");
try {
for (int c = 0; c < 5; c++) {
System.out.println(Thread.currentThread().getName() + " say: " + c);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " say: I'm interrupted :(");
}
System.out.println(Thread.currentThread().getName() + " say: Bye!");
return 0;
}
});
}
System.out.println(Thread.currentThread().getName() + " say: Starting workers");
try {
p.invokeAll(threads);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " say: I'm interrupted :(");
}
System.out.println(Thread.currentThread().getName() + " say: Bye!");
}
}, "new thread");
System.out.println("main say: Starting new thread");
t.start();
System.out.println("main say: Waiting a little...");
Thread.sleep(1250);
System.out.println("main say: Interrupting new thread");
t.interrupt();
// p.shutdown();
System.out.println(String.format("main say: Executor state: isShutdown: %s, isTerminated: %s",
p.isShutdown(),
p.isTerminated()));
System.out.println("main say: Bye...");
}
publicstaticvoidmain(String[]args)抛出Throwable{
final ExecutorService p=Executors.newFixedThreadPool(2);
System.out.println(“main说:你好,我是main!”);
线程t=新线程(新的可运行线程(){
@凌驾
公开募捐{
System.out.println(Thread.currentThread().getName()+“say:Starting monitor”);
线程监视器=新线程(新可运行(){
@凌驾
公开募捐{
试试{
while(true){
睡眠(1500);
System.out.println(Thread.currentThread().getName()+“说:我还在这里……哈哈哈”);
}
}捕捉(中断异常e){
System.out.println(Thread.currentThread().getName()+“说:再见!”);
}
}
}"监察";;
monitor.setDaemon(true);
monitor.start();
List threads=new ArrayList();
对于(int i=0;i<5;i++){
添加(新的可调用(){
@凌驾
公共整数调用()引发异常{
System.out.println(Thread.currentThread().getName()+“说:你好!”);
试一试{
对于(int c=0;c<5;c++){
System.out.println(Thread.currentThread().getName()+“说:”+c);
睡眠(500);
}
}捕捉(中断异常e){
System.out.println(Thread.currentThread().getName()+“说:我被打断了:(”);
}
System.out.println(Thread.currentThread().getName()+“说:再见!”);
返回0;
}
});
}
System.out.println(Thread.currentThread().getName()+“say:Starting workers”);
试一试{
p、 调用所有线程;
}捕获(中断异常e){
System.out.println(Thread.currentThread().getName()+“说:我被打断了:(”);
}
System.out.println(Thread.currentThread().getName()+“说:再见!”);
}
}“新线程”);
System.out.println(“主语句:启动新线程”);
t、 start();
System.out.println(“主要意思是:等待一点…”);
睡眠(1250);
System.out.println(“主语句:中断新线程”);
t、 中断();
//p.关机();
System.out.println(String.format(“main-say:Executor-state:isShutdown:%s,isTerminated:%s”),
p、 IsShutton(),
p、 已消除());
System.out.println(“主说:再见…”);
}
主要问题:当currentThread被中断时,为什么ThreadPool会中断其工作线程?我从哪里可以了解它的行为
为什么在本例中主线程不退出,但什么也不做?ThreadPool处于非活动状态,但未注册,并且已关闭,不处理其余任务。为什么会中断?
API中提到了对任务的中断:
抛出:
InterruptedException
-如果在等待时中断,则取消未完成的任务
因此,当在调用p.invokeAll(threads)
期间收到中断时,threads
中的所有任务都将被取消
API没有指定是否使用MayInterruptFrunning
调用,但如果查看ThreadPoolExecutor
继承其invokeAll()
实现的,可以看到任务在启用中断的情况下被取消:
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
/* ... */
try {
/* ... */
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
线程池没有任何特殊的魔法可以猜测您打算何时关闭它们;它们会等到您真正告诉它们时才关闭。状态文档:
池中的线程将一直存在,直到显式关闭shutdown
创建线程池时,需要确保它们最终被清理干净。通常是通过调用shutdown()
或shutdownNow()进行清理
。为什么有必要这样做?因为运行线程在Java垃圾收集上下文中是特殊的。运行线程是确定哪些对象不会被垃圾收集的起点,并且在它们仍在运行时永远不会被垃圾收集。Java程序在仍在运行线程时永远不会退出(当然,除非调用System.exit()
)
在某些特殊情况下,线程池可能没有正在运行的线程,因此会被垃圾收集。说明如下:
定稿
程序中不再引用且没有剩余线程的池将自动关闭。如果要确保即使用户忘记调用shutdown(),也会回收未引用的池
,则必须通过设置适当的保持活动时间,使用零核心线程的下限和/或设置allowCoreThreadTimeOut(布尔值)
,安排未使用的线程最终消亡
因此,我们可以将上面的示例修改为e
public static void main(String[] args) throws Throwable {
final ExecutorService p = Executors.newFixedThreadPool(2);
p.execute(new Runnable() { public void run() { } });
Thread.sleep(1000);
System.out.println(String.format("main say: Executor state: isShutdown: %s, isTerminated: %s",
p.isShutdown(),
p.isTerminated()));
}
final ThreadPoolExecutor p = new ThreadPoolExecutor(
0, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
final ThreadPoolExecutor p = new ThreadPoolExecutor(
2, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
p.allowCoreThreadTimeOut(true);