Executor
インターフェイスにはプレーンスレッド(管理など)に比べていくつかの利点があるという事実とは別に、実行中に実際の内部の違い(大きなパフォーマンスの違い、リソース消費など)があります。
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(runnable);
そして:
Thread thread = new Thread(runnable);
thread.start();
ここでは、単一のスレッドについてのみ質問しています。
Executors#newSingleThreadExecutor()は、フードの下にThreadPoolExecutorオブジェクトを作成し、
こちらのコードをご覧ください: http://www.docjar.com/html/api/Java/util/concurrent/Executors.Java.html
133 public static ExecutorService newSingleThreadExecutor() {
134 return new FinalizableDelegatedExecutorService
135 (new ThreadPoolExecutor(1, 1,
136 0L, TimeUnit.MILLISECONDS,
137 new LinkedBlockingQueue<Runnable>()));
138 }
ThreadPoolExecutorのドキュメント は、どのような状況で利点が得られるかを説明しています。
スレッドプールは、2つの異なる問題に対処します。これらは通常、タスクごとの呼び出しオーバーヘッドが削減されるため、多数の非同期タスクを実行するときのパフォーマンスが向上します。タスクのコレクションを実行するときに消費される、スレッドを含むリソースを制限および管理する手段。各ThreadPoolExecutorは、完了したタスクの数など、いくつかの基本的な統計も保持しています。
必要なのは、たった一度(たとえば1時間に1回)単一のスレッドを実行することだけである場合、パフォーマンスの観点から、ThreadPoolExecutor
を使用すると、機械全体(プール+スレッド)、メモリから破棄します。
ただし、この単一のスレッドを頻繁に(たとえば15秒ごとに)使用する場合、利点は、プールとスレッドを一度だけ作成し、それをメモリ内で使用し、常に新しいスレッドを作成する時間を節約するために常に使用します(15秒ごとに使用したい場合はかなり高価になる可能性があります)。
それはabstractionであり、それらは常に「コスト」で来ます:
大きな違いは、このサービスではmultipleタスクを送信できるのに対して、スレッドは1つのRunnableを実行できることです。一方、サービスを「シャットダウン」するなどのことを心配する必要があります。
経験則:パフォーマンスの側面はここでは「無視できる」ものに近いはずです。そのため、「より抽象的な」エグゼキューターサービスソリューションを好むでしょう。それはあなたの懸念を実際のスレッドから分離することができるからです。さらに重要なことは、そのサービスにdifferentのような実装を使用することを選択した場合、残りのコードはそのことを気にする必要がないことです。
簡単に言えば、抽象化にはコストがかかりますが、この場合、通常は「より抽象的な」ソリューションを好みます。最終的には、ソリューションの複雑さが軽減されるためです。
主な違いは、タスク実行ポリシーです。
Thread
インスタンスを作成するか、Thread
をサブクラス化することにより、基本的に1つのタスクを実行します。
一方、Executors.newSingleThreadExecutor()
を使用すると、複数のタスクを送信できます。これらのタスクはnotが同時に実行されることが保証されているため、次のthread confinementの利点を活用できます。
実行するRunnable
が1つだけの場合、それらの間には大きな違いはありませんがあります。
ExecutorService
などのThreadPoolExecutor
を作成するには、新しいスレッドを作成する以外にも何かする必要があるため、プレーンスレッドを使用する方が少し効率的です。たとえば、ブロッキングキューの作成、ポリシーの作成、これらは暗黙的に行われます。
そして、このランナブルが実行された後、エグゼキュータをshutdown
する必要があります。そうしないと、このプール内の単一スレッドは終了しません。