web-dev-qa-db-ja.com

SingleThreadExecutor VSプレーンスレッド

Executorインターフェイスにはプレーンスレッド(管理など)に比べていくつかの利点があるという事実とは別に、実行中に実際の内部の違い(大きなパフォーマンスの違い、リソース消費など)があります。

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(runnable);

そして:

Thread thread = new Thread(runnable);
thread.start();

ここでは、単一のスレッドについてのみ質問しています。

16
Magd Kudama

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秒ごとに使用したい場合はかなり高価になる可能性があります)。

8
krokodilko

それはabstractionであり、それらは常に「コスト」で来ます:

  • 一部の(潜在的な)量の「パフォーマンスペナルティ」
  • 「コントロール」の量を減らします(これがポイントです-低レベルの詳細に対処する必要がないため、必要な場合は...)

大きな違いは、このサービスではmultipleタスクを送信できるのに対して、スレッドは1つのRunnableを実行できることです。一方、サービスを「シャットダウン」するなどのことを心配する必要があります。

経験則:パフォーマンスの側面はここでは「無視できる」ものに近いはずです。そのため、「より抽象的な」エグゼキューターサービスソリューションを好むでしょう。それはあなたの懸念を実際のスレッドから分離することができるからです。さらに重要なことは、そのサービスにdifferentのような実装を使用することを選択した場合、残りのコードはそのことを気にする必要がないことです。

簡単に言えば、抽象化にはコストがかかりますが、この場合、通常は「より抽象的な」ソリューションを好みます。最終的には、ソリューションの複雑さが軽減されるためです。

2
GhostCat

主な違いは、タスク実行ポリシーです。

Threadインスタンスを作成するか、Threadをサブクラス化することにより、基本的に1つのタスクを実行します。

一方、Executors.newSingleThreadExecutor()を使用すると、複数のタスクを送信できます。これらのタスクはnotが同時に実行されることが保証されているため、次のthread confinementの利点を活用できます。

  • スレッドセーフではないオブジェクトにアクセスする場合、同期は不要です
  • 1つのタスクのメモリ効果は、次のタスクから見えることが保証されています
0
xuesheng

実行するRunnableが1つだけの場合、それらの間には大きな違いはありませんがあります。

ExecutorServiceなどのThreadPoolExecutorを作成するには、新しいスレッドを作成する以外にも何かする必要があるため、プレーンスレッドを使用する方が少し効率的です。たとえば、ブロッキングキューの作成、ポリシーの作成、これらは暗黙的に行われます。

そして、このランナブルが実行された後、エグゼキュータをshutdownする必要があります。そうしないと、このプール内の単一スレッドは終了しません。

0
xingbin