Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程中断时,为什么线程池会中断其工作线程?_Java_Multithreading_Threadpool - Fatal编程技术网

Java 线程中断时,为什么线程池会中断其工作线程?

Java 线程中断时,为什么线程池会中断其工作线程?,java,multithreading,threadpool,Java,Multithreading,Threadpool,请看这个例子。我从我的生产项目中得到它。Web服务器接收命令并启动新线程,该线程通过ADPool启动计算。当用户想要结束计算时,他发送另一个命令来中断这个新线程,线程池的工作线程将关闭。它工作得很好,但我不明白为什么 public static void main(String[] args) throws Throwable { final ExecutorService p = Executors.newFixedThreadPool(2); System

请看这个例子。我从我的生产项目中得到它。Web服务器接收命令并启动新线程,该线程通过ADPool启动计算。当用户想要结束计算时,他发送另一个命令来中断这个新线程,线程池的工作线程将关闭。它工作得很好,但我不明白为什么

 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);