17

目的:しばらくの間、特定のコードを実行します。Thread.sleep()VS Executor.scheduleWithFixedDelay()

質問:

while(true) { 
    execute(); 
    Thread.sleep(10 * 1000); 
} 

executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS); 

:パフォーマンスの面では、大きな違いはありますか?

もちろん、後者のオプションはもっとコーシャーです。それでも、私は「数日かけてThread.sleep()にさよならを言うためにレガシーコードをリファクタリングする」という冒険に着手すべきかどうかを知りたい。

更新: このコードは、スーパー/メガ/ハイパーロードの高い環境で動作します。

+0

から取られています。 –

+1

@Quoi:スケジュールされたエグゼキュータが多くのスケジュールされたタスクを実行し、タスクの数より少ないスレッドでそれらを実行できるので、それらは実際には同じではありません。スリープを使用している場合は、スケジュールするすべてのタスクのスレッドが必要です。 –

+5

*スリープ状態の操作の実行について質問しているのはなぜですか? – Dan

答えて

6

あなたは数十秒というスリープ時間を扱っています。ここでスリープオプションを変更することで節約できる可能性は、ナノ秒またはマイクロ秒です。

私は後者のスタイルを毎回好んでいますが、前者の場合はそれを変更するのに多くの費用がかかりますが、「パフォーマンスの向上」は特に正当な理由ではありません。

EDIT再:8000件のスレッド

8000のスレッドが非常に多くあります。スケジュールされたエグゼキュータに移動するだけで、システムにかかる負荷の量を制御できるようになります。さまざまな起床時間についてのあなたの要点はわかっているはずですが、大きなリスクはすべて眠っているスレッドの踏み台であり、その後は引き続き連続して起きて、すべてのシステムリソースを競合すると主張します。

私はこれらのすべてをスケジュールされたエグゼキュータをスケジュールされたスレッドプールに投入するのに時間を費やします。最も制限されたリソース(#コア、#IOパスなど)と同じ数だけ同時に実行し、いくつかのスロープをピックアップします。これにより、レイテンシを犠牲にしても優れたスループットが得られます。

Thread.sleep()メソッドでは、何が起こっているのかを制御するのが非常に難しく、スループットがの両方の遅延で失われる可能性があります。

詳細なアドバイスが必要な場合は、おそらくもっと詳しくしようとしていることを説明する必要があります。

+0

私は懸念しているのは、8,000のスレッドがあり、スリープしているスレッドが、GCでの副次的な問題を引き起こす可能性があるような遅い優先度で実行される可能性があるということです。 – rudgirello

1

Javaバージョンについては言及していないので、状況が変わる可能性があります。

Javaのソースコードからもわかるように、大きな違いは内部的に書かれていることです。 のSun Java 1.6あなたは第二のアプローチを使用する場合、ネイティブコードも待機中にもたらし、システムへのの呼び出しを通知するために

。だから、より効率的なスレッドとCPUに優しい方法で。

しかし、もう一度コントロールが緩くなり、10秒間スリープ状態になることを考えれば、コードでは予測できなくなります。

予測性がさらに必要な場合は、確かにオプション1を使用できます。

また、レガシーシステムでは、このようなことに遭遇したときには、80%のチャンスがありますが、現在はより良い方法がありますが、魔法の数字は理由のため残ります(残りの20%)。 、自身の責任でそれを変更:)

1

異なるシナリオがタイマーが継続的に更新されたタスクのキューを作成します

  1. 、があります。タイマが完了すると、すぐにガベージコレクションされないことがあります。したがって、より多くのタイマーを作成すると、ヒープ上にオブジェクトが追加されるだけです。 Thread.sleep()はスレッドを一時停止するだけなので、メモリオーバーヘッドが極端に低くなる
  2. Timer/TimerTaskもタスクの実行時間を考慮しているため、より正確になります。そして、それはマルチスレッドの問題(デッドロックの回避など)をうまく処理します。
  3. スレッドが例外をとり、強制終了されると、それが問題になります。しかし、TimerTaskはそれを処理します。以前の実行での失敗に関係なく実行されます
  4. TimerTaskの利点は、あなたの意図をはるかに良く(コードの可読性)表現し、すでにcancel()機能が実装されていることです。

リファレンスは、私はどちらも同じであり、 `scheduleWithFixedDelay`がスリープコールをカプセル化だと思うhere