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

时间:2014-12-15 10:47:43

标签: java multithreading threadpool threadpoolexecutor

我正在尝试理解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 个答案:

答案 0 :(得分:4)

来自ExecutorService#shutdown()的文件:

  

启动以前提交的任务的有序关闭   已执行,但不会接受任何新任务。

这意味着您提交给执行人的所有工作都将在他们自己的时间内完成,而不会中断或“赶紧”#34;它们,执行程序将正确完成工作线程,但服务也不会接受新的工作,也不会立即终止。

比较ExecutorService#shutdownNow(),它会尝试尽快终止。

答案 1 :(得分:3)

执行程序创建的Worker线程是内部类,它们具有对执行程序本身的引用。 (他们需要它能够看到队列,runstate等等!)运行线程不是垃圾收集的,所以当池中的每个线程都有该引用时,它们将使执行器保持活动状态直到所有线程都死亡。如果你不手动做一些事情来阻止线程,它们将永远运行,你的JVM永远不会关闭。

如果5个线程只生成了3个任务,那么2个未使用的线程将永远不会被启动但是引用将保持不变,直到在finalize()中调用shutdown或所有活动线程在那里完成执行。

以下是JAVA Docs的评论:

  

程序中不再引用且没有剩余线程的池将自动关闭。如果您希望确保回收未引用的池&gt;即使用户忘记调用shutdown(),那么您必须通过设置适当的保持活动时间,使用零核的下限来安排未使用的线程&gt;最终死亡&gt;线程和/或设置allowCoreThreadTimeOut(boolean)。

答案 2 :(得分:2)

  

在这种情况下,JVM是否负责处理子线程?

操作系统管理线程并确定它们何时运行。

  

此外,我创建了一个包含5个线程的线程池,但只提交了3个任务。当主线程退出时,剩余的2个线程是否会被终止?

不,线程一直运行,直到你关闭它们。

  

执行程序服务关闭时实际发生了什么?

线程被中断,不会启动任何新任务。但是,如果您有一个忽略中断的任务,它可以无限期地继续运行。

当最后一个非deamon线程停止时,触发了关闭钩子(如果有的话)。

答案 3 :(得分:0)

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.