为什么从Executors实用程序类返回的ExecutorService的execute()方法无法自然终止

时间:2018-06-08 06:38:15

标签: java currency threadpoolexecutor java-threads

众所周知,java.util.concurrent.Executors包含许多方法,例如

  • newCachedThreadPool
  • newFixedThreadPool
  • newScheduledThreadPool
  • newSingleThreadExecutor
  • newSingleThreadScheduledExecutor

    他们返回ExecutorService,其中包含execute(Runnable task)方法。但是,在调用从上述工厂方法返回的execute(Runnable task) ExecutorService时,只能通过调用shutdown()shutdownNow()

例如,如果我们将以下代码添加到main方法,

ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test")); 

调用主程序永远不会终止,因为shutdown()shutdownNow()未被调用。因此, main 中包含以下代码段的程序将终止

ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test"));
e.shutdown();

但是,ExecutorService的某些子类(例如通过调用Executors.newWorkStealingPoolForkJoinPool返回的子类)可以在不调用shutdown()shutdownNow()

所以我的问题是:为什么execute()的{​​{1}}从上述工厂方法返回,以“new”开头“如果不从设计角度调用ExecutorServiceshutdown(),则不会终止?

2 个答案:

答案 0 :(得分:0)

Rui,你的例子挂起的答案很简单。默认情况下,ExecutorService中的线程是非守护程序线程,只要有非守护程序线程在运行,Java程序就不会退出。如果你不想要这种行为,你需要做的就是定义一个创建守护程序线程的ThreadFactory,如下所示:

public class Test {
    static ThreadFactory mThreadFactory = new ThreadFactory() {
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setDaemon(true);
            return t;
        }
    };

    public static void main(String[] args) {
        ExecutorService e = Executors.newSingleThreadExecutor(mThreadFactory);
        e.execute(new Runnable() { public void run() { System.out.println("test"); } });
    }
}

答案 1 :(得分:0)

简要介绍一下java线程:有两种类型的线程 - 守护进程和非守护进程。程序在其所有非守护程序线程都已完成执行时终止。守护程序线程只能在程序运行的时间内运行,并且不会阻止终止,例如garbage collector。当一个java程序启动它的所有线程,除了主线程是守护进程。

newSingleThreadExecutor()及其defaultThreadFactory()创建非守护程序线程。哪种方式有意义 - 您正在创建一个等待工作的线程池,应该是您明确意图将其关闭。

另一方面,ForkJoinPool从底层线程池中抽象出来。所以它可以使用守护进程线程,因为通常你打算等待任务执行。