尽管在Daemon中创建了池,但Executors.newCacheThreadPool创建的线程不是daemon。

时间:2018-06-28 06:28:13

标签: java java-8 daemon executorservice

为避免将自定义ThreadFactory传递到ThreadPoolExecutor以直接使用Executors.newCachedThreadPool();

我创建了一个线程mainDaemonThread,使用Executors.newCachedThreadPool();,提交任务,并且在mainDaemonThread启动之前,我将其设置为daemon,据我所知,一旦父级线程是一个守护进程,默认情况下,它创建的所有线程均为daemon

Daemon Thread

  

当在某个线程中运行的代码创建新的Thread对象时,新线程的优先级最初设置为与创建线程的优先级相等,并且当且仅当创建线程是守护程序时,该线程才是守护程序线程。

>

那么为什么Executors.newCachedThreadPool();不遵循规则?与此相关的一些设计偏好?

import static java.lang.System.out;
public static void main(String... args) throws InterruptedException {
    Thread mainDaemonThread = new Thread(() -> {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(() -> {
            try {
                out.println(Thread.currentThread().isDaemon());
                Thread.sleep(1000);
                out.println(Thread.currentThread().isDaemon());
            } catch(InterruptedException ignored) {
                ignored.printStackTrace();
            }
        });
    });
    mainDaemonThread.setDaemon(true);
    mainDaemonThread.start();
    mainDaemonThread.join();
    out.println(Thread.currentThread().isDaemon());
}

演示的输出:

false
false
false

任何帮助将不胜感激,谢谢〜

1 个答案:

答案 0 :(得分:4)

我想这不是关于原因的正确答案,但是:

您链接的文档适用于Thread类,并记录了“手动”创建新Thread的行为。它只是不适用于您提交给ExecutorService的任务(尽管我明白您为什么会期望这样做)。

如果您查看源代码,newCachedThreadPool执行程序将使用(内部)DefaultThreadFactory来显式创建一个非守护程序Thread

public Thread newThread(Runnable r) {
    Thread t = new Thread(group, r,
                          namePrefix + threadNumber.getAndIncrement(),
                          0);
    if (t.isDaemon())
        t.setDaemon(false); // ta-da
    if (t.getPriority() != Thread.NORM_PRIORITY)
        t.setPriority(Thread.NORM_PRIORITY);
    return t;
}

如果希望执行者创建守护程序线程,则可以将Executors#newCachedThreadPool(ThreadFactory)方法与确实创建守护程序Thread的工厂一起使用。由于ThreadFactory是一个功能接口,因此就像

Executors#newCachedThreadPool(Thread::new);