2012-01-05 4 views
2

私はスレッドプールを管理するためにThreadPoolExecutorを使用します。ThreadPoolExecutorのコアスレッドを有効にして余分なスレッドを取り除く方法keepAliveTimeが期待どおりに動作しない

  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でない場合、「アライブ」スレッド(アイドルまたはビジー)の数を知る方法はありますか?

ありがとうございます。

+0

何かについて考える:スレッドが作成されたときから、または実行するタスクがなくなったときからkeepAliveがカウントダウンを開始するのですか? – LazyCubicleMonkey

+0

@ LazyCubicleMonkey私はそれが後者であるべきだと思います。 [setKeepAliveTime](http://enos.itcollege.ee/~jpoial/docs/api/java/util/concurrent/ThreadPoolExecutor.html#setKeepAliveTime%28long,%20java.util.concurrent.TimeUnit%29)で、タスクを実行した後の**時間**としての "時間"。いずれにしても、coreThreadTimeOutが許可されていない場合、コアスレッドに適用すべきではありません。 – arosima

答えて

1

Java 7がテストに合格しました。どうやらJava 6にはバグがあります。そのコードを読むと、キューが空のときにすべてのスレッドが終了することができます。これはコアスレッドにとって間違いです。

+0

はい、同意します。私はまた、ソースコードをチェックアウトしました。プール内に残っているスレッドの数を確認することなく、各作業者がタスクを完了した後、プールから自分自身を削除します。しかし、私はもっと混乱してきています。keepAliveTimeを0に設定すると、コアスレッドが実際にプールに保持されているようです。どのように機能するのですか? – arosima

0

プールサイズが目標サイズであることは間違いありません。スレッドをシャットダウンすることについての保証はないと思います(バックグラウンドチェッカーはありません)。私はそのヒントを思いついたと思います。アイドル状態のスレッドは、オーバーヘッドがなくなります。

+1

Java 6のソースコードから、各ワーカーは自分自身をプールから削除し、タスクを完了した後にpoolSizeを減らします。 poolSizeはthreadCountではなくactiveCountに似ています。 – arosima

1

@arosima keepAliveTimeは、コアスレッドではなく余分なスレッドでのみ有効です。コアスレッドは常にプールに保持されます。私はまた、理解するためにanother answerを書いた、それが助けて欲しい。

関連する問題