203

ExecutorService の submitまたはexecuteをどのように選択すればよいですか? 返される値が気にならない場合は?

両方をテストした場合、戻り値を除いて、2 つの間に違いは見られませんでした。

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.execute(new Task());

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
threadExecutor.submit(new Task());
4

7 に答える 7

210

例外/エラー処理に関して違いがあります。

execute()いくつかを生成するキューに入れられたタスクは、タスクを実行ThrowableするUncaughtExceptionHandlerためのThreadを呼び出します。UncaughtExceptionHandlerカスタム ハンドラがインストールされていない場合は、通常、Throwableスタック トレースをに出力するデフォルトのSystem.errが呼び出されます。

一方、 でThrowableキューに入れられたタスクによって生成された は、への呼び出しから生成された にsubmit()をバインドします。それを呼び出すと、オリジナルを原因としてがスローされます ( を呼び出すことでアクセスできます)。ThrowableFuturesubmit()get()FutureExecutionExceptionThrowablegetCause()ExecutionException

于 2010-10-21T10:33:59.973 に答える
11

戻り値の型を気にしない場合は、execute を使用してください。Future が返されないだけで、submit と同じです。

于 2010-10-14T02:09:21.007 に答える
8

Javadoc から取得:

メソッドは、実行をキャンセルしたり、完了を待つために使用できる {@link Future} を作成して返すことにより、submit基本メソッド {@link Executor# } を拡張します。execute

個人的には、execute の使用を好みます。これは、より宣言的であると感じられるからです。ただし、これは実際には個人的な好みの問題です。

詳細情報を提供するには:ExecutorService実装の場合、 への呼び出しによって返されるコア実装Executors.newSingleThreadedExecutor()ThreadPoolExecutor.

submit呼び出しはその親によって提供され、すべてのAbstractExecutorService呼び出しは内部で実行されます。execute はThreadPoolExecutor直接オーバーライド/提供されます。

于 2010-10-14T01:35:06.107 に答える
2

完全な回答は、ここで公開された2つの回答の構成です(さらに少し「余分な」):

  • タスクを送信する (実行するのではなく) と、結果を取得したり、アクションをキャンセルしたりするために使用できるフューチャが返されます。この種のコントロールはありませんexecute(戻り値の型が id であるためvoid
  • executea Runnablewhileは引数として aまたは a のsubmitいずれかを取ることができます (2 つの違いの詳細については、以下を参照してください)。RunnableCallable
  • executeチェックされていない例外はすぐにバブルアップし (チェックされた例外をスローすることはできません!!!)、結果として返されるフューチャーにあらゆるsubmit種類の例外をバインドし、(ラップされた) 例外を呼び出した場合にのみスローされます。取得する Throwable は のインスタンスであり、このオブジェクトを呼び出すと、元の Throwable が返されます。future.get()ExecutionExceptiongetCause()

さらにいくつかの(関連する)ポイント:

  • 目的のタスクでsubmit結果を返す必要がない場合でも、Callable<Void>(を使用する代わりにRunnable) を使用できます。
  • タスクのキャンセルは、割り込みメカニズムを使用して行うことができます。キャンセル ポリシーの実装方法の例を次に示します。

要約すると、 (対 a ) を使用する方がsubmit良いCallable方法executeですRunnable。そして、Brian Goetz による「Java concurrency in practice」から引用します。

6.3.2 結果を伴うタスク: Callable と Future

Executor フレームワークは、基本的なタスク表現として Runnable を使用します。Runnable はかなり限定的な抽象化です。run は、値を返したり、チェック例外をスローしたりすることはできませんが、ログ ファイルへの書き込みや共有データ構造への結果の配置などの副作用が生じる可能性があります。データベース クエリの実行、ネットワーク経由でのリソースの取得、複雑な関数の計算など、多くのタスクは実質的に遅延計算です。これらのタイプのタスクの場合、Callable はより優れた抽象化です。メイン エントリ ポイントである call が値を返すことを想定し、例外をスローする可能性があることを想定しています.7 Executors には、Runnable など、他のタイプのタスクをラップするためのユーティリティ メソッドがいくつか含まれています。 Callable を持つ java.security.PrivilegedAction。

于 2016-04-29T21:55:49.947 に答える
2

From the Javadoc:

The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.

So depending on the implementation of Executor you may find that the submitting thread blocks while the task is executing.

于 2013-06-13T08:58:06.627 に答える
1

受け入れられた答えに追加するだけです-

ただし、タスクからスローされた例外は、execute() でサブミットされたタスクに対してのみ、キャッチされていない例外ハンドラーになります。submit() で executor サービスに送信されたタスクの場合、スローされた例外は、タスクのリターン ステータスの一部と見なされます。

ソース

于 2019-11-26T13:54:04.157 に答える