2

ThreadPoolExecutorを使用してスレッドプールを管理しています。私たちが欲しいのは:

  1. プールのスレッド数がcorePoolSize未満の場合は、新しいタスクのために新しいスレッドを開始します。
  2. プールにcorePoolSizeを超えるスレッドがあり、すべてがビジーである場合は、maxPoolSizeに達するまで、新しいタスクのために新しいスレッドを開始します。その場合、タスクを拒否します。
  3. アイドル状態のスレッドのcorePoolSize数を維持し、keepAliveTimeを超えてアイドル状態になっていると、余分なスレッドは停止します。

Java6ドキュメントによると、keepAliveTimeは上記のように機能するはずです。しかし、私のテストコードでは、一貫して機能しません。

keepAliveTimeを0に設定すると、正常に機能し、コアスレッドを常に存続させ、終了時に余分なスレッドを終了します。
ただし、以下に示すように、keepAliveTimeを正の値に設定すると、コアスレッドであるかどうかに関係なく、すべてのアイドル状態のスレッドが終了するように見えます。

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 500, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
assertFalse("Not allow core threads to time out.", executor.allowsCoreThreadTimeOut());
Task task_1 = new Task(1000);
Task task_2 = new Task(1000);
Task task_3 = new Task(1000);
executor.execute(task_1);
executor.execute(task_2);
executor.execute(task_3);
Thread.sleep(1050L);
assertEquals("Completed 3 tasks.", 3, executor.getCompletedTaskCount());
assertEquals("Three threads are in the pool.", 3, executor.getPoolSize());
Thread.sleep(600L);
//////// This assertion will fail: **expected <2> but was <0>**
assertEquals("Two threads are in the pool.", 2, executor.getPoolSize());

////----
private static class Task implements Runnable {
    private long sleepMillis;
    public Task(final long sleepMillis) {
        this.sleepMillis = sleepMillis;
    }
    public void run() {
        try { Thread.sleep(sleepMillis);
        } catch (Exception e) { System.out.println(e); }
    }
}

keepAliveTimeまたはgetPoolSizeについて誤解はありますか?getPoolSizeが正しいAPIでない場合、「生きている」スレッド(アイドルまたはビジー)の数を知るにはどうすればよいですか?

前もって感謝します。

4

3 に答える 3

1

Java7はテストに合格します。どうやらJava6にはバグがあります。そのコードを読み取ると、キューが空になるとすべてのスレッドが終了する可能性があります。これは、コアスレッドにとっては間違いなく間違っています。

于 2012-01-05T09:18:28.093 に答える
0

プールサイズが目標サイズであると確信しています。スレッドをシャットダウンするという保証はないと思います (バックグラウンド チェッカーはありません)。単なるヒントだと思います。アイドル スレッドのオーバーヘッドはほとんどありません。

于 2012-01-05T08:40:33.690 に答える