JavaでExecutorServiceをデーモンにする



デーモンスレッドとは (6)

はい。

通常のスレッドではなく、デーモンスレッドを作成する独自のThreadFactoryクラスを作成するだけでThreadFactoryます。

私はJava 1.6でExecutoreServiceを使用しています。

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

私のメインスレッドが終了すると(スレッドプールによって処理されるすべてのタスクと共に)、このプールは明示的に呼び出すまで私のプログラムがシャットダウンするのを防ぎます

pool.shutdown();

このプールで使用されている内部スレッドをデアモンスレッドに変えて、何とかこれを呼び出す必要はありませんか? または、私はここで何かを逃しています。


一定期間使用しないとすべてのスレッドを終了するExecutorServiceを作成するための組み込み機能がすでにありますThreadPoolExecutorを作成し、目的のタイミング情報を渡してから、このallowCoreThreadTimeout(true)サービスでallowCoreThreadTimeout(true)を呼び出します。

/**
 * 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コメントの注釈を参照する:このスレッドプールエグゼキュータは、アプリケーションが終了したときに自動的にシャットダウンしません。 エグゼキュータは、アプリケーションが終了した後も引き続き実行されますが、 keepAliveTimeより長くはなりません。 厳密なアプリケーション要件に応じて、 keepAliveTimeが数秒より長くなければならない場合は、 keepAliveTimeの回答がより適切な場合があります。スレッドがデーモンスレッドに設定されている場合、アプリケーションが終了すると直ちに終了します終了します。


GuavaのThreadFactoryBuilderクラスを使用します。

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

Guavaをまだ使用していない場合は、 Pshemoの回答の先頭にあるようなThreadFactoryサブクラスを使用します


Marco13の答えにはおそらく最も単純で好ましい解決策がありますので、投票の差(私の答えは数年前です)または合格マークに惑わされないようにしてください(私の解決策はOPの状況に適していません)。

ThreadFactoryを使用してExecutor内のスレッドをデーモンに設定できます。 これはデーモンスレッドとなるようにエグゼキュータサービスに影響を与え、他のデーモン以外のスレッドがなければ停止します。 ここに簡単な例があります:

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);

しかし、実行を終了させるエグゼキュータを取得したいと同時に、アプリケーションが完了したときに同時にshutdown()メソッドを自動的に呼び出す場合は、 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();
        }
    }
});

このソリューションは@ Marco13と似ていますが、独自のThreadPoolExecutorを作成する代わりに、 Executors#newFixedThreadPool(int nThreads)によって返されたThreadPoolExecutorを修正することができます。 方法は次のとおりです。

ExecutorService ex = Executors.newFixedThreadPool(nThreads);
 if(ex instanceof ThreadPoolExecutor){
    ThreadPoolExecutor tp = (ThreadPoolExecutor) ex;
    tp.setKeepAliveTime(time, timeUnit);
    tp.allowCoreThreadTimeOut(true);
}

私は通常、スレッドをデーモンスレッドとして実行したいので、次のようにユーティリティクラスを追加しました:

import java.util.concurrent.ThreadFactory;

public class DaemonThreadFactory implements ThreadFactory {

    public final static ThreadFactory instance = 
                    new DaemonThreadFactory();

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}

これにより、 DaemonThreadFactory.instanceExecutorServiceに簡単に渡すことができます。

ExecutorService exec = Executors.newFixedThreadPool(
    4, DaemonThreadFactory.instance
);

またはRunnableからデーモンスレッドを簡単に起動するために使用します。

DaemonThreadFactory.instance.newThread(
    () -> { doSomething(); }
).start();




java-threads