スレッドエグゼキュータでshutdown()
を呼び出さないと、アプリケーションが終了することはありません。
ExecutorServiceをシャットダウンするためのベストプラクティスは次のとおりです。
ExecutorService service = null;
try {
service = Executors.newSingleThreadExecutor();
// add tasks to thread executor
…
} finally {
if (service != null) service.shutdown();
}
Javaはtry-with-resourcesの概念を知っているので、これができたらいいのではないでしょうか。
try (service = Executors.newSingleThreadExecutor())
{
// add tasks to thread executor
…
}
その ExecutorService には、実際には2つのシャットダウン関連のメソッドがあります。サービスをシャットダウンする両方の方法が理にかなっているという単純な事実に基づいています。
したがって、サービスをどのように自動クローズしますか?すべての人に役立つ一貫した方法で?!
したがって、私の目には合理的な説明があります。ExecutorServiceには、「閉じる」ような操作が1つもないため、ExecutorServiceをAutoClosableにすることはできません。でも2つ!
そして、そのような自動クローズサービスをうまく利用できると思うなら、「委任」を使用して独自の実装を作成するのは5分です。または、おそらく10分です。これは、クローズ操作としてshutdown()
を呼び出す1つのバージョンを作成するためです。代わりにshutdownNow()
を実行するもの。
これは平凡な回避策です
ExecutorService service = Executors.newSingleThreadExecutor();
try (Closeable close = service::shutdown) {
}
または、チェックされた例外が気になる場合は、次のように記述できます。
interface MyCloseable extends AutoCloseable {
void close();
}
その後
ExecutorService service = Executors.newSingleThreadExecutor();
try (MyCloseable close = service::shutdown) {
}
もちろん、割り当てとtry
ステートメントの間に何かを入れたり、service
ステートメントの後にtry
ローカル変数を使用したりしないでください。
警告がある場合は、代わりにfinally
を使用してください。
AutoCloseableがエグゼキュータにとってどこに役立つのかわかりません。 try-with-resourcesは、メソッドのスコープ内で初期化、使用、および解放できるもの用です。これは、ファイル、ネットワーク接続、jdbcリソースなど、ファイルがすばやく開かれ、使用され、クリーンアップされる場合に最適です。ただし、エグゼキュータ、特にスレッドプールは、おそらくアプリケーションの存続期間中、長期間利用できるようにしたいものであり、DIフレームワークが認識しているメソッドを持つことができるシングルトンサービスなどに注入される傾向があります。アプリケーションのシャットダウンを呼び出して、エグゼキュータをクリーンアップします。この使用パターンは、try-with-resourcesがなくても正常に機能します。
また、try-with-resourcesの背後にある大きな動機は、例外がマスクされないようにすることです。これはエグゼキュータではそれほど考慮されません。すべての例外スローはエグゼキュータに送信されたタスクで発生します。例外マスキングは問題ではありません。