を使用してタスクをスケジュールするコードがありますjava.util.Timer
。私は周りを見回してExecutorService
いて、同じことができるのを見ました。ここでこの質問です。タスクをスケジュールして使用Timer
したExecutorService
ことがありますが、あるタスクを別のタスクよりも優れている点は何ですか。
また、誰かがTimer
クラスを使用したかどうかを確認し、ExecutorService
解決された問題に遭遇しました。
を使用してタスクをスケジュールするコードがありますjava.util.Timer
。私は周りを見回してExecutorService
いて、同じことができるのを見ました。ここでこの質問です。タスクをスケジュールして使用Timer
したExecutorService
ことがありますが、あるタスクを別のタスクよりも優れている点は何ですか。
また、誰かがTimer
クラスを使用したかどうかを確認し、ExecutorService
解決された問題に遭遇しました。
回答:
実際のJava同時実行性によると:
Timer
システムクロックの変化に敏感になる可能性ScheduledThreadPoolExecutor
があります。Timer
には実行スレッドが1つしかないため、実行時間の長いタスクが他のタスクを遅延させる可能性があります。ScheduledThreadPoolExecutor
任意の数のスレッドで構成できます。さらに、必要に応じて(を提供することによりThreadFactory
)作成されたスレッドを完全に制御できます。TimerTask
が1つのスレッドをkillでスローすると、Timer
デッドが発生します:-( ...つまり、スケジュールされたタスクは実行されなくなります。ScheduledThreadExecutor
実行時例外をキャッチするだけでなく、必要に応じてそれらを処理できます(afterExecute
からのメソッドをオーバーライドすることによりThreadPoolExecutor
)。スローされた例外はキャンセルされますが、他のタスクは引き続き実行されます。のScheduledThreadExecutor
代わりに使用できる場合はTimer
、使用してください。
もう1つ... ScheduledThreadExecutor
Java 1.4ライブラリでは使用できませんが、クラスを含むJava 1.2、1.3、1.4へのJSR 166(java.util.concurrent
)のバックポートがありますScheduledThreadExecutor
。
利用できる場合、Java 5エグゼキューターフレームワークを使用しない理由を考えるのは困難です。呼び出し:
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
とScheduledExecutorService
同様の機能を備えたTimer
(つまり、シングルスレッド化されます)が、アクセスがわずかにスケーラブルになる可能性があります(内部では、Timer
クラスのように完全な同期ではなく並行構造を使用します)。aを使用するScheduledExecutorService
と、次のような利点もあります。
newScheduledThreadPoolExecutor()
またはScheduledThreadPoolExecutor
クラスを参照)Timer
私が思いつくことができる唯一の理由については:
TimerTask
するもう1つの理由scheduledExecutionTime()
は、に同等のメソッドがないように見えるメソッドの可用性ですScheduledExecutorService
。
タイマーの使用に関するいくつかのより良い習慣はここにあります:
http://tech.puredanger.com/2008/09/22/timer-rules/
一般的に、迅速で汚れたものにはTimerを使用し、より堅牢な使用法にはExecutorを使用します。
ScheduledThreadPoolExecutorの Oracleドキュメントページから
A ThreadPoolExecutorさらに所定の遅延後に実行するコマンドをスケジュールすることができ、又は定期的に実行します。このクラスは、複数のワーカースレッドが必要な場合、またはThreadPoolExecutor(このクラスが拡張する)の追加の柔軟性または機能が必要な場合に、Timerよりも適しています。
ExecutorService/ThreadPoolExecutor
または、ScheduledThreadPoolExecutor
複数のワーカースレッドがある場合は当然の選択です。
ExecutorService
以上の長所Timer
Timer
ExecutorService
特にForkJoinPoolExecutorService
などのフレーバーを使用する複数のタスクとは異なり、利用可能なCPUコアを利用できません ExecutorService
複数のタスク間の調整が必要な場合に、コラボレーションAPIを提供します。N個のワーカータスクを送信し、すべてのタスクが完了するまで待機する必要があるとします。あなたはinvokeAll APIでそれを簡単に達成できます。複数のTimer
タスクで同じことを実現したい場合、それは簡単ではありません。ThreadPoolExecutorは、スレッドのライフサイクルを管理するためのより優れたAPIを提供します。
スレッドプールは2つの異なる問題に対処します。これらは通常、タスクごとの呼び出しオーバーヘッドが減少するため、多数の非同期タスクを実行するときのパフォーマンスを向上させます。また、スレッドプールは、タスク。各ThreadPoolExecutorは、完了したタスクの数など、いくつかの基本的な統計も維持します
いくつかの利点:
a。スレッドのライフサイクルを作成/管理/制御し、スレッド作成コストのオーバーヘッドを最適化できます
b。タスクの処理(Work Stealing、ForkJoinPool、invokeAll)などを制御できます。
c。スレッドの進行状況と状態を監視できます
d。より優れた例外処理メカニズムを提供します
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の堅牢性が必要ないときに行います。