Java でのタイマーとタイマータスクとスレッド + スリープの比較
-
12-09-2019 - |
質問
ここで同様の質問を見つけましたが、満足のいく回答はありませんでした。それで、もう一度質問を言い換えると、
定期的に (たとえば 1 分間隔で) 実行する必要があるタスクがあります。スリープ付きの無限ループを持つ新しいスレッドを作成するのとは対照的に、Timertask と Timer を使用してこれを行う利点は何ですか?
timertask を使用したコード スニペット -
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
Thread と sleep を使用したコード スニペット -
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
ロジックの実行にインターバル時間よりも時間がかかる場合は、特定のサイクルを逃しても心配する必要はありません。
これについてコメントしてください。
アップデート:
最近、Timer と Thread.sleep() の使用の別の違いを発見しました。現在のシステム時刻が午前 11 時であると仮定します。何らかの理由でシステム時刻を午前 10:00 にロールバックすると、タイマーは午前 11:00 に達するまでタスクの実行を停止しますが、Thread.sleep() メソッドは支障なくタスクの実行を継続します。これは、これら 2 つの間で何を使用するかを決定する際の主要な意思決定者となる可能性があります。
解決
TimerTaskをの利点は、それが(すなわち、コードの読みやす)より良いあなたの意図を表現することであり、それはすでにキャンセル()機能が実装されています。
それは同様にあなた自身の一例として、短い形式で書くことができることに注意します:
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
}, 0, 60 * 1000);
他のヒント
タイマ/ TimerTaskをも考慮にあなたのタスクの実行時間を要するので、もう少し正確になります。そして、それは(などデッドロックを避けるなど)マルチスレッドの問題をよりよく扱います。そしてもちろん、それはいくつかの自家製溶液の代わり十分にテストされた標準コードを使用することは通常勧めします。
私にはわからない、なぜ私は書いていたプログラムは、タイマーを使用していたし、それは私が/スリープ問題が解決スレッドにそれを変更したら、ヒープサイズは、絶えず増加していたのです。
、それが問題です。 しかし、TimerTaskを、それの世話をします。これは、前回の実行に関係なく、障害の実行されます。
Javaスレッドとsleep
メソッドを使用してこのタスクを管理に対する1つの重要な引数があります。あなたは、ループ内で無期限に滞在し、スリープ状態に置くことによって、スレッドを休止状態にwhile(true)
を使用しています。何NewUploadServer.getInstance().checkAndUploadFiles();
は、いくつかの同期リソースを取る場合。他のスレッドは飢餓があなたのアプリケーション全体を遅くすることができ起こる可能性があり、これらのリソースにアクセスすることができません。エラーこれらの種類を診断するのは難しいですし、それは彼らのexistanceを防ぐことをお勧めします。
他のaproachは、その間にリソースを使用して、他のスレッドをさせながら、あなたのNewUploadServer.getInstance().checkAndUploadFiles();
のrun()
メソッドを呼び出すことによって、あなた、すなわちTimerTask
に重要なコードの実行をトリガーします。
から Timer
ドキュメンテーション:
Java 5.0はjava.util.concurrentパッケージを導入しました。その中の並行性ユーティリティの1つは、特定のレートまたは遅延でタスクを繰り返し実行するためのスレッドプールであるスケジュールされたreadpoolexecutorです。複数のサービススレッドを許可し、さまざまな時間単位を受け入れ、サブクラス化Timertask(実行可能な実装)を必要としないため、Timer/Timertaskの組み合わせのためのより多用途の交換です。1つのスレッドでScheduleDThreadPoolexecutorを構成すると、タイマーと同等になります。
とても好みです ScheduledThreadExecutor
の代わりに Timer
:
Timer
すべてのタイマーのタスクを順番に実行するために使用される単一のバックグラウンド スレッドを使用します。したがって、タスクはすぐに完了する必要があります。そうしないと、後続のタスクの実行が遅れます。しかし、次の場合にはScheduledThreadPoolExecutor
任意の数のスレッドを設定でき、以下を提供することで完全な制御も可能です。ThreadFactory
.Timer
を利用するため、システム クロックの影響を受ける可能性があります。Object.wait(long)
方法。しかしScheduledThreadPoolExecutor
ではありません。- TimerTask でスローされたランタイム例外はその特定のスレッドを強制終了するため、それを処理できる限り Timer がデッドになります。
ScheduledThreadPoolExecutor
他のタスクに影響が及ばないようにします。 Timer
提供しますcancel
メソッドを使用してタイマーを終了し、スケジュールされたタスクを破棄しますが、現在実行中のタスクには干渉せず、タスクを終了させます。ただし、タイマーがデーモン スレッドとして実行されている場合、キャンセルするかどうかに関係なく、すべてのユーザー スレッドの実行が終了するとすぐに終了します。
タイマーとスレッドスリープの比較
タイマーを活用する Object.wait
そしてそれは違う Thread.sleep
- 待っています(
wait
) スレッドに通知できます (使用してnotify
) 別のスレッドによって実行されますが、スリープ中のスレッドでは実行できず、中断することしかできません。 - 待機 (および通知) はモニター オブジェクト上で同期されたブロック内で発生する必要がありますが、スリープは発生しません。
- スリープではロックが解放されませんが、待機では、wait が呼び出されたオブジェクトのロックが解放されます。
私は非常によく似た何かを見ています、私はあなたの問題を理解すると思います。私は、いくつかの30分ごとおよび日おきにいくつかを繰り返しているタイマーを持っています。私は読み、コメントは私が見たものから、それはすべてのタスクが完了されることはありませんので、ガベージコレクションが実行されることはありませんように見えます。私はタイマーがスリープ状態のとき、ガベージコレクションの実行と思うだろうが、私はそれを見て、そうでないドキュメントに従っていないです。
私は、新しいスレッドを生成すると、完了したことを考えると、ガベージコレクションを許可します。
誰かが私は痛みになるだろう継承何書き換え、私は間違っていることを証明してください。