Javaタイマーvs ExecutorService?


263

を使用してタスクをスケジュールするコードがありますjava.util.Timer。私は周りを見回してExecutorServiceいて、同じことができるのを見ました。ここでこの質問です。タスクをスケジュールして使用TimerしたExecutorServiceことがありますが、あるタスクを別のタスクよりも優れている点は何ですか。

また、誰かがTimerクラスを使用したかどうかを確認し、ExecutorService解決された問題に遭遇しました。


1
また、さらに充実した機能が必要な場合は、quartzをチェックしてください。これは、スケジューリングのようなcron、クラスター対応スケジューリング、ジョブの個別制御(一度に1つの実行、依存関係などの概念)を含む、より多くのジョブ制御を提供します。--Tim
ティム・

回答:


313

実際のJava同時実行性によると:

  • Timerシステムクロックの変化に敏感になる可能性ScheduledThreadPoolExecutorがあります。
  • Timerには実行スレッドが1つしかないため、実行時間の長いタスクが他のタスクを遅延させる可能性があります。ScheduledThreadPoolExecutor任意の数のスレッドで構成できます。さらに、必要に応じて(を提供することによりThreadFactory)作成されたスレッドを完全に制御できます。
  • 実行時例外TimerTaskが1つのスレッドをkillでスローすると、Timerデッドが発生します:-( ...つまり、スケジュールされたタスクは実行されなくなります。ScheduledThreadExecutor実行時例外をキャッチするだけでなく、必要に応じてそれらを処理できます(afterExecuteからのメソッドをオーバーライドすることによりThreadPoolExecutor)。スローされた例外はキャンセルされますが、他のタスクは引き続き実行されます。

ScheduledThreadExecutor代わりに使用できる場合はTimer、使用してください。

もう1つ... ScheduledThreadExecutorJava 1.4ライブラリでは使用できませんが、クラスを含むJava 1.2、1.3、1.4へのJSR 166(java.util.concurrent)のバックポートがありますScheduledThreadExecutor


63

利用できる場合、Java 5エグゼキューターフレームワークを使用しない理由を考えるのは困難です。呼び出し:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

ScheduledExecutorService同様の機能を備えたTimer(つまり、シングルスレッド化されます)が、アクセスがわずかにスケーラブルになる可能性があります(内部では、Timerクラスのように完全な同期ではなく並行構造を使用します)。aを使用するScheduledExecutorServiceと、次のような利点もあります。

  • 必要に応じてカスタマイズできます(newScheduledThreadPoolExecutor()またはScheduledThreadPoolExecutorクラスを参照)
  • 「1回限り」の実行は結果を返すことができます

Timer私が思いつくことができる唯一の理由については:

  • Java 5より前で使用可能
  • J2MEにも同様のクラスが用意されており、アプリケーションの移植が容易になります(ただし、この場合、抽象化の共通層を追加することはそれほど難しくありません)。

1
を使用TimerTaskするもう1つの理由scheduledExecutionTime()は、に同等のメソッドがないように見えるメソッドの可用性ですScheduledExecutorService
Rohit Agarwal

3
別のメモ:2k17でこのコメントを書いています。J2MEはもうありません。それはすでに死んでいます。
msangel 2017

1
Javaタイマークラスはくだらないです。
JohnyTex 2017年

26

ExecutorServiceはより新しく、より一般的です。タイマーは、スケジュールされたものを定期的に実行する単なるスレッドです。

ExecutorServiceはスレッドプールの場合もあれば、クラスター内の他のシステム全体に分散していて、1回限りのバッチ実行などを行う場合もあります。

それぞれが何を決定するために提供するかを見てください。



8

ScheduledThreadPoolExecutorの Oracleドキュメントページから

A ThreadPoolExecutorさらに所定の遅延後に実行するコマンドをスケジュールすることができ、又は定期的に実行します。このクラスは、複数のワーカースレッドが必要な場合、またはThreadPoolExecutor(このクラスが拡張する)の追加の柔軟性または機能が必要な場合に、Timerよりも適しています。

ExecutorService/ThreadPoolExecutorまたは、ScheduledThreadPoolExecutor複数のワーカースレッドがある場合は当然の選択です。

ExecutorService以上の長所Timer

  1. TimerExecutorService特にForkJoinPoolExecutorServiceなどのフレーバーを使用する複数のタスクとは異なり、利用可能なCPUコアを利用できません
  2. ExecutorService複数のタスク間の調整が必要な場合に、コラボレーションAPIを提供します。N個のワーカータスクを送信し、すべてのタスクが完了するまで待機する必要があるとします。あなたはinvokeAll APIでそれを簡単に達成できます。複数のTimerタスクで同じことを実現したい場合、それは簡単ではありません。
  3. ThreadPoolExecutorは、スレッドのライフサイクルを管理するためのより優れたAPIを提供します。

    スレッドプールは2つの異なる問題に対処します。これらは通常、タスクごとの呼び出しオーバーヘッドが減少するため、多数の非同期タスクを実行するときのパフォーマンスを向上させます。また、スレッドプールは、タスク。各ThreadPoolExecutorは、完了したタスクの数など、いくつかの基本的な統計も維持します

    いくつかの利点:

    a。スレッドのライフサイクルを作成/管理/制御し、スレッド作成コストのオーバーヘッドを最適化できます

    b。タスクの処理(Work Stealing、ForkJoinPool、invokeAll)などを制御できます。

    c。スレッドの進行状況と状態を監視できます

    d。より優れた例外処理メカニズムを提供します


5

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); 

private final Timer timer = new Timer(true);

これは、executorserviceの堅牢性が必要ないときに行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.