Java Timer vs ExecutorService?
-
03-07-2019 - |
質問
java.util.timer
を使用してタスクをスケジュールするコードがあります。周りを見回してみると、 ExecutorService
で同じことができることがわかりました。ここでこの質問、タイマーと ExecutorService
を使用してタスクをスケジュールしましたか?
また、誰かが Timer
クラスを使用し、 ExecutorService
が解決した問題に遭遇したかどうかを確認したかった。
解決
Java同時実行の実践によると:
-
Timer
はシステムクロックの変化に敏感な場合がありますが、ScheduledThreadPoolExecutor
はそうではありません。 -
Timer
には実行スレッドが1つしかないため、長時間実行されるタスクは他のタスクを遅延させる可能性があります。ScheduledThreadPoolExecutor
は、任意の数のスレッドで構成できます。さらに、必要に応じて、作成されたスレッドを完全に制御できます(ThreadFactory
を提供することにより)。 -
TimerTask
でスローされた実行時例外は、その1つのスレッドを強制終了するため、Timer
がデッドになります:-( ...つまり、スケジュールされたタスクは実行されなくなります。ScheduledThreadExecutor
はランタイム例外をキャッチするだけでなく、必要に応じて処理することもできます(ThreadPoolExecutor
からafterExecute
メソッドをオーバーライドすることにより)。例外をスローしたタスクはキャンセルされますが、他のタスクは引き続き実行されます。
Timer
の代わりに ScheduledThreadExecutor
を使用できる場合は、そうします。
もう1つ... ScheduledThreadExecutor
はJava 1.4ライブラリでは使用できませんが、 JSR 166のバックポート( java.util.concurrent
)からJava 1.2、1.3、1.4 へ。これには ScheduledThreadExecutor
クラスがあります。
他のヒント
利用可能な場合、Java 5 executorフレームワークを使用するしない理由を考えるのは困難です。呼び出し:
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
は、 Timer
と同様の機能を備えた ScheduledExecutorService
を提供します(つまり、シングルスレッドになります)が、アクセスはわずかに拡張可能です(内部では、 Timer
クラスのように完全な同期ではなく、並行構造を使用します)。 ScheduledExecutorService
を使用すると、次のような利点も得られます。
- 必要に応じてカスタマイズできます(
newScheduledThreadPoolExecutor()
またはScheduledThreadPoolExecutor
クラスを参照) - 「ワンオフ」実行は結果を返すことができます
Timer
にこだわる唯一の理由については、次のとおりです。
- Java 5より前のバージョンで利用可能です
- 同様のクラスがJ2MEで提供されているため、アプリケーションの移植が容易になります(ただし、この場合、共通の抽象化レイヤーを追加するのはそれほど難しくありません)
ExecutorServiceはより新しく、より一般的です。タイマーは、スケジュールされたものを定期的に実行する単なるスレッドです。
ExecutorServiceはスレッドプールであるか、クラスター内の他のシステムに分散していて、1回限りのバッチ実行などを実行することもあります。
各オファーの決定内容を確認してください。
タイマーの使用に関するいくつかの優れたプラクティスを次に示します。
http://tech.puredanger.com/2008/09/22 / timer-rules /
一般的に、手早く汚れたものにはTimerを使用し、より堅牢な使用にはExecutorを使用します。
Executors.newSingleThreadScheduledExecutor()よりもTimerを好むことがある私の理由は、デーモンスレッドで実行するためにタイマーが必要なときに、よりクリーンなコードを取得できるからです。
比較
private final ThreadFactory threadFactory = new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
};
private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
with
private final Timer timer = new Timer(true);
executorserviceの堅牢性が必要ないときにこれを行います。
ThreadPoolExecutor 。指定された遅延後に実行するコマンドを定期的にスケジュールしたり、定期的に実行したりできます。複数のワーカースレッドが必要な場合、または(このクラスが拡張する)ThreadPoolExecutorの追加の柔軟性または機能が必要な場合、このクラスは Timer よりも望ましいです。
ExecutorService / ThreadPoolExecutor
または ScheduledThreadPoolExecutor
は、複数のワーカースレッドがある場合は当然の選択です。
Timer
ExecutorService
の長所
-
タイマー
は、ExecutorService
とは異なり、特に ForkJoinPool -
ExecutorService
は、複数のタスク間の調整が必要な場合にコラボレーションAPIを提供します。 N個のワーカータスクを送信し、すべてのタスクが完了するまで待つ必要があると仮定します。 invokeAll API。複数のTimer
タスクで同じことを達成したい場合、それは簡単ではありません。 -
ThreadPoolExecutor スレッドのライフサイクルを管理するためのより良いAPIを提供します。
スレッドプールは、2つの異なる問題に対処します。通常、タスクごとの呼び出しオーバーヘッドが削減されるため、多数の非同期タスクを実行するときのパフォーマンスが向上し、実行時に消費されるスレッドなどのリソースを制限および管理する手段を提供しますタスクのコレクション。各ThreadPoolExecutorは、完了したタスクの数など、いくつかの基本的な統計も保持します
いくつかの利点:
a。スレッドのライフサイクルを作成/管理/制御できます&スレッド作成コストのオーバーヘッドを最適化する
b。タスク(ワークスティーリング、ForkJoinPool、invokeAll)などの処理を制御できます。
c。スレッドの進行状況と正常性を監視できます
d。より優れた例外処理メカニズムを提供します