2011-03-08 3 views
6

私はマルチスレッドアプリケーションを持っています。 Thread.start()を使用してスレッドを手動で開始する場合、すべての同時スレッドは正確に25%のCPUを使用します(まさしく1つのコア - これはクワッドコアマシン上にあります)。したがって、2つのスレッドを実行する場合、CPU使用率は正確に50%です。Java:ExecutorServiceは手動のスレッド実行より効率が悪いですか?

ExecutorServiceを使用してスレッドを実行すると、1つの "ゴースト"スレッドがCPUリソースを消費するようです。 1つのスレッドは、25%の代わりに50%、2つのスレッドを使用する75%などを使用します。

これは、Windowsタスクマネージャのアーティファクトの一種かもしれませんか?

Excutorサービスコードが

ExecutorService executor = Executors.newFixedThreadPool(threadAmount); 

for (int i = 1; i < 50; i++) { 
    Runnable worker = new ActualThread(i); 
    executor.execute(worker); 
} 
executor.shutdown(); 
while (!executor.isTerminated()) { 

} 
System.out.println("Finished all threads"); 

とThread.start()のコードです:

ActualThread one= new ActualThread(2,3); 
ActualThread two= new ActualThread(3,4); 
... 

Thread threadOne = new Thread(one); 
Thread threadTtwo = new Thread(two); 
... 

threadOne.start(); 
threadTwo.start(); 
... 
+1

2番目の例でスレッドが終了するのを待つコードはどこですか? –

答えて

16

ここにあなたの問題です:

while (!executor.isTerminated()) { 

} 

あなたの "メイン" メソッドが回転していますCPUは何もしません。代わりにinvokeAll()を使用すると、スレッドはビジー待機なしでブロックされます。 invokeAll()以来

final ExecutorService executor = Executors.newFixedThreadPool(threadAmount); 
final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(); 

for (int i = 1; i < 50; i++) { 
    tasks.add(Executors.callable(new ActualThread(i))); 
} 
executor.invokeAll(tasks); 
executor.shutdown(); // not really necessary if the executor goes out of scope. 
System.out.println("Finished all threads"); 

は、ヘルパーメソッドExecutors.callable()の使用を注意し、Callableのコレクションを望んでいます。実際にこれを使ってFutureのコレクションを取得することもできます。これは、タスクが実際に出力として必要なものを生成している場合に便利です。

+1

+1、わずかに小さい変更は 'awaitTermination'を使うことです。 –

+0

@Mark、そうですが、 'invokeAll()'があなたのために存在するとき、手動のアクロバットはなぜですか?このモデルは、エグゼキュータの再利用も奨励しています。これはしばしば良いことです...いずれにしても、いずれも動作します。 – andersoj

関連する問題