104

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

定期的に(たとえば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:00AMであるとします。何らかの理由でシステム時刻を10:00AMにロールバックすると、タイマーは11:00 AMに達するまでタスクの実行を停止しますが、Thread.sleep()メソッドは支障なくタスクの実行を続行します。これは、これら2つの間で何を使用するかを決定する際の主要な意思決定者になる可能性があります。

4

7 に答える 7

67

TimerTaskの利点は、意図をはるかによく表現し(つまり、コードの可読性)、cancel()機能がすでに実装されていることです。

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

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
于 2009-09-21T07:55:46.077 に答える
12

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

于 2009-09-21T08:02:35.863 に答える
8

Timer ドキュメントから:

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

したがってScheduledThreadExecutor、の代わりに優先しますTimer

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

タイマーとThread.sleep

タイマーを利用しObject.waitており、Thread.sleep

  1. 待機中の(wait)スレッドはnotify別のスレッドから(を使用して)通知できますが、スリープ中のスレッドは通知できず、中断することしかできません。
  2. 待機(および通知)は、モニターオブジェクトで同期されたブロックで発生する必要がありますが、スリープは発生しません。
  3. スリープ状態ではロックが解除されませんが、待機すると、待機が呼び出されたオブジェクトのロックが解除されます。
于 2018-09-13T04:01:36.573 に答える
5

理由はわかりませんが、私が書いていたプログラムはタイマーを使用していて、スレッド/スリープの問題に変更すると、ヒープサイズが絶えず増加していました。

于 2011-10-03T03:40:08.440 に答える
4

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

他のアプローチは、あなたにとって重要なコードの実行をトリガーします。つまり、その間に他のスレッドにリソースを使用させながら、あなたのメソッドをNewUploadServer.getInstance().checkAndUploadFiles();呼び出します。run()TimerTask

于 2009-09-21T08:25:50.840 に答える
4

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

于 2014-02-06T19:45:48.430 に答える
2

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

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

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

于 2014-11-20T03:24:48.613 に答える