8

私はこのトピックに不慣れです...私は Executors.newFixedThreadPool( 10 ) で作成された ThreadPoolExecutor を使用しており、プールがいっぱいになった後、 RejectedExecutionException を取得し始めています。プールが解放されたときに新しいタスクを拒否して開始するのではなく、エグゼキューターに新しいタスクを「待機」状態にするように「強制」する方法はありますか?

ありがとう

この https://github.com/evilsocket/dsploit/issues/159に関する問題

関連するコード行https://github.com/evilsocket/dsploit/blob/master/src/it/evilsocket/dsploit/net/NetworkDiscovery.java#L150

4

4 に答える 4

22

使用するExecutors.newFixedThreadPool(10);と、タスクがキューに入れられ、スレッドの準備が整うまで待機します。

この方法は

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

ご覧のとおり、使用されるキューは無制限ですが (それ自体が問題になる可能性があります)、キューがいっぱいになることはなく、拒否されることもありません。

ところで: CPU バウンドのタスクがある場合、最適なスレッド数は

int processors = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(processors);

状況を説明するテストクラス

public static void main(String... args) {
    ExecutorService es = Executors.newFixedThreadPool(2);
    for (int i = 0; i < 1000 * 1000; i++)
        es.submit(new SleepOneSecond());

    System.out.println("Queue length " + ((ThreadPoolExecutor) es).getQueue().size());
    es.shutdown();
    System.out.println("After shutdown");
    try {
        es.submit(new SleepOneSecond());
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

static class SleepOneSecond implements Callable<Void> {
    @Override
    public Void call() throws Exception {
        Thread.sleep(1000);
        return null;
    }
}

版画

Queue length 999998
After shutdown
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@e026161 rejected from java.util.concurrent.ThreadPoolExecutor@3e472e76[Shutting down, pool size = 2, active threads = 2, queued tasks = 999998, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2013)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:816)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1337)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:132)
    at Main.main(Main.java:17)
于 2012-11-08T10:49:07.853 に答える
4

スレッドがを呼び出す可能性が非常に高く、これはfalseexitに設定され、エグゼキュータをシャットダウンしますが、次のようになります。mStopped

  • 実行中のスレッドがwhile (!mStopped)ループの途中にある可能性があり、によってシャットダウンされたエグゼキュータにタスクを送信しようとしますexit
  • whileに加えられた変更が表示されないため、の条件はtrueを返しますmStopped(そのフラグの周りで同期の形式を使用しません)。

私は提案します:

  • mStopped揮発性にする
  • ループの途中でエグゼキュータがシャットダウンされた場合を処理します(たとえば、RejectedExecutionExceptionをキャッチするか、おそらくより良い方法:exitメソッドでシャットダウンするのではなく、whileループの後でエグゼキュータをシャットダウンします)。
于 2012-11-08T11:08:03.653 に答える