web-dev-qa-db-ja.com

Java Timer vs ExecutorService?

Java.util.timerを使用してタスクをスケジュールするコードがあります。私は周りを見回して、ExecutorServiceが同じことをするのを見ました。この質問は、タイマーとExecutorServiceを使用してタスクをスケジュールしたことがありますか?

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

252
kal

使用できる場合、理由を考えるのは困難ですnot Java 5 executor frameworkを使用する。呼び出し:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

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

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

私が考えることができるTimerに固執する唯一の理由については:

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

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

ExecutorServiceはスレッドプールであるか、クラスター内の他のシステムに分散していて、1回限りのバッチ実行などの処理を行うこともあります。

それぞれの決定内容を見てください。

22
Dustin

タイマーの使用に関するいくつかの優れたプラクティスは次のとおりです。

http://tech.puredanger.com/2008/09/22/timer-rules/

一般に、手早く汚れたものにはTimerを使用し、より堅牢な使用にはExecutorを使用します。

15
Alex Miller

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

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

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

ExecutorServiceに対するTimerの長所

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

    スレッドプールは、2つの異なる問題に対処します。通常、タスクごとの呼び出しオーバーヘッドが削減されるため、多数の非同期タスクを実行するときのパフォーマンスが向上し、スレッドのコレクションを実行するときに消費されるリソースを制限および管理する手段を提供しますタスク。各ThreadPoolExecutorは、完了したタスクの数など、いくつかの基本的な統計も保持します

    いくつかの利点:

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

    b。タスク(ワークスティーリング、ForkJoinPool、invokeAll)などの処理を制御できます。

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

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

6
Ravindra babu

時々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の堅牢性が必要ないときにこれを行います。

5
Siamaster