Java线程池:空闲线程会发生什么

5

我正在尝试理解Java中的多线程。我编写了以下Java程序来测试线程池。

public class ThreadPoolTest
{
    public static void main(String[] args)
    {
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for( int i = 0; i < 3; i++ )
        {
            executorService.submit(new Task(i+1));
        }
        executorService.shutdown();                     

    }

    public static class Task implements Runnable
    {
        private int taskId;

        public Task(int id)
        {
            taskId = id;
        }

        @Override
        public void run() {
            System.out.println("Executing task " + taskId + " performed by " + Thread.currentThread().getName() );
            try
            {
                Thread.sleep(3000);
            }
            catch(InterruptedException interruptEx)
            {
                System.out.println(Thread.currentThread().getName() + " got interrupted ");
            }
            System.out.println("Finished executing task " + taskId );
        }
    }
}

主线程创建执行器,执行器创建5个线程,但我只提交了3个任务。之后,我关闭执行器。运行代码时,主线程先结束而子线程还在运行。这种情况下,JVM会处理子线程吗?
同时,我创建了一个拥有5个线程的线程池,但只提交了3个任务。当主线程退出时,剩余的2个线程会被终止吗?
执行器服务何时被关闭,具体会发生什么?
4个回答

4

根据ExecutorService#shutdown()文档:

触发有序关闭,之前提交的任务会被执行,但不会接受新的任务。

这意味着你提交给Executor的所有作业将在其自己的时间内完成,而不会中断或“加速”它们,执行程序将正确地完成工作线程,但服务既不会接受新的作业,也不会立即终止。

相比之下,ExecutorService#shutdownNow()尝试尽快终止。


3
执行器创建的Worker线程是内部类,它们有一个对执行器本身的引用。(它们需要这个引用来查看队列、运行状态等!)正在运行的线程不会被垃圾回收,因此池中每个线程都有该引用,直到所有线程死亡后,它们将保持执行器的活动状态。如果您不手动停止线程,则它们将永远运行,您的JVM将永远不会关闭。
在5个线程的情况下,只生成3个任务,2个未使用的线程将永远不会启动,但其引用将保持不变,直到在finalize()中调用shutdown或所有活动线程完成其执行为止。
以下是JAVA文档中的注释:
自动关闭不再在程序中引用且没有剩余线程的池。如果您希望确保即使用户忘记调用shutdown(),也能回收未引用的池,则必须安排未使用的线程最终死亡,方法是设置适当的保持活动时间,使用零核心线程的下限和/或设置allowCoreThreadTimeOut(boolean)。

1
但是空闲线程会运行什么?如果我使用一个线程,然后很长时间都没有任务要执行,一旦初始任务完成后,那个线程会运行什么呢?它是否会忙等待并占用CPU资源? - aneesh joshi

2
在��种情况下,JVM是否会管理子线程?
操作系统管理线程并确定何时运行它们。
我创建了一个有5个线程的线程池,但只提交了3个任务。当主线程退出时,剩余的2个线程会被终止吗?
不会,线程会一直运行,直到你关闭它们。
当执行器服务被关闭时,会发生什么?
线程会被中断,并且不会启动新的任务。然而,如果你有一个忽略中断的任务,它可能会一直运行下去。
当最后一个非守护线程停止时,关闭挂钩(如果有)会被触发。

-1

JVM是否会处理子线程

JVM只有在完成所有守护线程后才会完成其执行。如果您将其创建为非守护程序,则它将等待所有非守护程序线程完成。

当主线程退出时,剩余的2个线程是否会终止

线程将以按需模式创建。因此,这里只创建了3个线程而不是5个。

执行器服务关闭时会发生什么

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接