タイマーとタイマータスクとスレッド+ Javaでのスリープ


102

ここで同様の質問をしましたが、満足のいく答えがありませんでした。質問をもう一度言い換えると

定期的に(たとえば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 t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();

ロジックの実行にインターバル時間以上かかる場合でも、特定のサイクルを見逃しても心配する必要はありません。

これについてコメントしてください。

更新:
最近、TimerとThread.sleep()の使用に別の違いが見つかりました。現在のシステム時刻が午前11:00であるとします。なんらかの理由でシステム時間を10:00 AMにロールバックすると、Timerは11:00 AMに達するまでタスクの実行を停止しますが、Thread.sleep()メソッドは問題なくタスクを実行し続けます。これは、これら2つの間で何を使用するかを決定する際の主要な意思決定者になる可能性があります。


21
順序のポイント:TimerとTimerTaskは廃止されており、実質的にはExecutorServiceに置き換えられていますが、まだ要点は残っています。
skaffman 2009

ヒントをありがとう、ExecutorServiceを使用することにしました:)
Keshav

回答ありがとうございました、きっと理解を深めてくれました!
ケシャフ

6
タイマーは廃止されておらず、単一のスレッドのみが必要な場合に推奨されます。(java.sun.com/javase/6/docs/api/java/util/Timer.html
ジャスティン・

2
TimerとTimerTaskは、ExecutorServiceが存在しないJME環境でも役立ちます(JME Java 1.3ベースから...)。
スーパーファミコン

回答:


67

TimerTaskの利点は、意図がはるかによく表現され(コードの読みやすさなど)、cancel()機能がすでに実装されていることです。

それはあなた自身の例と同様に短い形式で書くことができることに注意してください:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);

タイマーが毎日、午後2時と午前9時の2つの特定の時間に使用されている場合...値を指定するにはどうすればよいですか。上記のコードで... @Zed?
gumuruh 2016

12

Timer / TimerTaskでは、タスクの実行時間も考慮されるため、少し正確になります。また、マルチスレッドの問題(デッドロックの回避など)をより適切に処理します。そしてもちろん、通常は、自家製のソリューションではなく、十分にテストされた標準コードを使用することをお勧めします。


5

なぜなのかはわかりませんが、作成中のプログラムはタイマーを使用していて、ヒープサイズが常に増加していたため、スレッド/スリープの問題に変更すると解決しました。


9
タイマーは、継続的に更新されるタスクのキューを作成します。タイマーが完了すると、すぐにガベージコレクションされない場合があります。したがって、タイマーをさらに作成しても、ヒープにオブジェクトが追加されるだけです。Thread.sleep()はスレッドを一時停止するだけなので、メモリのオーバーヘッドは非常に低くなります。
ダリルジェロー2013

4

スレッドが例外を取得して強制終了した場合、それは問題です。しかし、TimerTaskがそれを処理します。前の実行の失敗に関係なく実行されます。


4

Timer ドキュメントから:

Java 5.0はjava.util.concurrentパッケージを導入し、その中の同時実行ユーティリティの1つは、指定されたレートまたは遅延でタスクを繰り返し実行するためのスレッドプールであるScheduledThreadPoolExecutorです。これは、複数のサービススレッドを許可し、さまざまな時間単位を受け入れ、TimerTaskをサブクラス化する必要がないため(Runnableを実装するだけ)、Timer / TimerTaskの組み合わせのより用途の広い代替品です。1つのスレッドでScheduledThreadPoolExecutorを構成すると、Timerと同等になります。

したがってScheduledThreadExecutorTimer次の代わりに優先します。

  • Timerタイマーのすべてのタスクを順番に実行するために使用される単一のバックグラウンドスレッドを使用します。したがって、タスクはすばやく完了する必要があります。そうしないと、後続のタスクの実行が遅れます。ただし、ScheduledThreadPoolExecutor任意の数のスレッドを構成でき、を提供することで完全な制御も可能ThreadFactoryです。
  • TimerObject.wait(long)メソッドを使用するため、システムクロックの影響を受けやすくなります。しかし、そうでScheduledThreadPoolExecutorはありません。
  • TimerTaskでスローされるランタイム例外はその特定のスレッドを強制終了ScheduledThreadPoolExecutorし、他のタスクに影響を与えないように処理できる場所でTimerを停止します。
  • Timercancelタイマーを終了し、スケジュールされたタスクを破棄するメソッドを提供しますが、現在実行中のタスクを妨害せずに終了させます。ただし、タイマーがデーモンスレッドとして実行されている場合、それをキャンセルするかどうかにかかわらず、すべてのユーザースレッドの実行が終了するとすぐにタイマーが終了します。

タイマーvs Thread.sleep

タイマーを利用してObject.waitおり、それとは異なりますThread.sleep

  1. 待機中の(wait)スレッドはnotify別のスレッドから(を使用して)通知を受けることができますが、スリープ中のスレッドは通知できず、割り込みのみが可能です。
  2. 待機(および通知)は、モニターオブジェクトで同期されたブロックで発生する必要がありますが、スリープは発生しません。
  3. スリープしてもロックは解除されませんが、待機するとオブジェクトのロックが解除され、待機が要求されます。

非常に役立つ情報に加えて、無限ループでThread.sleepを使用すると、少ない時間遅延でCPU使用率が高くなる可能性があります。
Amir Fo

3

Javaスレッドとsleepメソッドを使用してこのタスクを管理することに反対する重要な議論が1つあります。あなたは、使用しているwhile(true)ループ内で無期限に滞在し、スリープ状態に置くことによって、スレッドを休止します。NewUploadServer.getInstance().checkAndUploadFiles();同期されたリソースを使用する場合はどうでしょうか。他のスレッドはこれらのリソースにアクセスできなくなり、飢餓が発生してアプリケーション全体の速度が低下する可能性があります。これらの種類のエラーは診断が困難であり、それらの存在を防ぐことをお勧めします。

もう1つのアプローチは、重要なコードの実行をトリガーします。つまり、リソースを使用している他のスレッドにその間NewUploadServer.getInstance().checkAndUploadFiles();run()メソッドを呼び出しますTimerTask


16
私はこの議論を理解していません。どちらの選択肢もスレッドから同じメソッドを起動します。どちらの選択肢も、実行を待機している間、スレッドでスリープしています。2つの選択肢の間に飢餓の違いはありません。
satur9nine

2

私はあなたの問題を理解していると思います、私は非常に類似した何かを見ています。私は定期的なタイマーを持っています。30分ごとと数日ごとのタイマーがあります。私が読んだ内容と私が見たコメントから、すべてのタスクが完了することはないため、ガベージコレクションは実行されないようです。タイマーがスリープ状態のときにガベージコレクションは実行されると思いますが、タイマーは表示されず、ドキュメントによると表示されません。

新しいスレッドの生成が完了し、ガベージコレクションが可能になると思います。

誰かが私が間違っていることを証明してください、私が継承したものを書き換えることは苦痛になるでしょう。

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