Turning an ExecutorService to daemon in Java

后端 未结 8 2176
无人共我
无人共我 2020-11-27 02:39

I am using an ExecutoreService in Java 1.6, started simply by

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

When my main

相关标签:
8条回答
  • 2020-11-27 03:02

    I would use Guava's ThreadFactoryBuilder class.

    ExecutorService threadPool = Executors.newFixedThreadPool(THREADS, new ThreadFactoryBuilder().setDaemon(true).build());
    

    If you're not already using Guava, I'd go with a ThreadFactory subclass like described at the top of Pshemo's answer

    0 讨论(0)
  • 2020-11-27 03:04

    There already is a built-in functionality for creating an ExecutorService that terminates all threads after a certain period of inactivity: You can create a ThreadPoolExecutor, pass it the desired timing information, and then call allowCoreThreadTimeout(true) on this executor service:

    /**
     * Creates an executor service with a fixed pool size, that will time 
     * out after a certain period of inactivity.
     * 
     * @param poolSize The core- and maximum pool size
     * @param keepAliveTime The keep alive time
     * @param timeUnit The time unit
     * @return The executor service
     */
    public static ExecutorService createFixedTimeoutExecutorService(
        int poolSize, long keepAliveTime, TimeUnit timeUnit)
    {
        ThreadPoolExecutor e = 
            new ThreadPoolExecutor(poolSize, poolSize,
                keepAliveTime, timeUnit, new LinkedBlockingQueue<Runnable>());
        e.allowCoreThreadTimeOut(true);
        return e;
    }
    

    EDIT Referring to the remarks in the comments: Note that this thread pool executor will not automatically shut down when the application exits. The executor will continue to run after the application exits, but no longer than the keepAliveTime. If, depending on the precise application requirements, the keepAliveTime has to be longer than a few seconds, the solution in the answer by Pshemo may be more appropriate: When the threads are set to be daemon threads, then they will end immediately when the application exits.

    0 讨论(0)
  • 2020-11-27 03:09

    This solution is similar to @Marco13's but instead of creating our own ThreadPoolExecutor, we can modify the one returned by Executors#newFixedThreadPool(int nThreads). Here's how:

    ExecutorService ex = Executors.newFixedThreadPool(nThreads);
     if(ex instanceof ThreadPoolExecutor){
        ThreadPoolExecutor tp = (ThreadPoolExecutor) ex;
        tp.setKeepAliveTime(time, timeUnit);
        tp.allowCoreThreadTimeOut(true);
    }
    
    0 讨论(0)
  • 2020-11-27 03:16

    Yes.

    You simply need to create your own ThreadFactory class that creates daemon threads rather than regular threads.

    0 讨论(0)
  • 2020-11-27 03:18

    Probably simplest and preferred solution is in Marco13's answer so don't get fooled by vote difference (mine answer is few years older) or acceptance mark (it just means that mine solution was appropriate for OP circumstances not that it is best).


    You can use ThreadFactory to set threads inside Executor to daemons. This will affect executor service in a way that it will also become daemon thread so it (and threads handled by it) will stop if there will be no other non-daemon thread. Here is simple example:

    ExecutorService exec = Executors.newFixedThreadPool(4,
            new ThreadFactory() {
                public Thread newThread(Runnable r) {
                    Thread t = Executors.defaultThreadFactory().newThread(r);
                    t.setDaemon(true);
                    return t;
                }
            });
    
    exec.execute(YourTaskNowWillBeDaemon);
    

    But if you want to get executor which will let its task finish, and at the same time will automatically call its shutdown() method when application is complete, you may want to wrap your executor with Guava's MoreExecutors.getExitingExecutorService.

    ExecutorService exec = MoreExecutors.getExitingExecutorService(
            (ThreadPoolExecutor) Executors.newFixedThreadPool(4), 
            100_000, TimeUnit.DAYS//period after which executor will be automatically closed
                                 //I assume that 100_000 days is enough to simulate infinity
    );
    //exec.execute(YourTask);
    exec.execute(() -> {
        for (int i = 0; i < 3; i++) {
            System.out.println("daemon");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    
    0 讨论(0)
  • 2020-11-27 03:21

    If you have a known list of tasks, you don't need daemon threads at all. You can simply call shutdown() on the ExecutorService after submitting all your tasks.

    When your main thread is complete, use the awaitTermination() method to allow time for the submitted tasks to complete.The currently submitted tasks will be executed, and the thread pool will terminate its control thread once they have been completed.

    for (Runnable task : tasks) {
      threadPool.submit(task);
    }
    threadPool.shutdown();
    /*... do other stuff ...*/
    //All done, ready to exit
    while (!threadPool.isTerminated()) {
      //this can throw InterruptedException, you'll need to decide how to deal with that.
      threadPool.awaitTermination(1,TimeUnit.SECOND); 
    }
    
    0 讨论(0)
提交回复
热议问题