web-dev-qa-db-ja.com

Thread.sleepの使用が悪い理由

この繰り返される質問におApび申し上げますが、満足のいく答えはまだ見つかりません。ほとんどの質問には、固有のユースケースがありました。
Java-thread.sleepの代替
JavaでThread.sleep(1000)の使用をスキップ/回避する他の方法はありますか?

私の質問は、非常に一般的な使用例です。条件が完了するまで待ちます。何らかの操作を行います。状態を確認してください。条件が真でない場合は、しばらく待ってから同じ操作を再度実行してください。

例えばcreateAPIテーブルを呼び出してDynamoDBテーブルを作成するメソッドを検討してください。 DynamoDBテーブルがアクティブになるまでに時間がかかるため、メソッドはDescribeTable APIを呼び出して、一定の間隔でステータスをポーリングします(たとえば5分-スレッドスケジューリングによる偏差は許容されます)。テーブルが5分以内にアクティブになる場合はtrueを返し、そうでない場合は例外をスローします。

擬似コードは次のとおりです。

public void createDynamoDBTable(String name) {
  //call create table API to initiate table creation

  //wait for table to become active
  long endTime = System.currentTimeMillis() + MAX_WAIT_TIME_FOR_TABLE_CREATE;

  while(System.currentTimeMillis() < endTime) {
    boolean status =  //call DescribeTable API to get status;
    if(status) {
         //status is now true, return
         return
    } else {
        try {
            Thread.sleep(10*1000);
        } catch(InterruptedException e) {
        }
    }
  }

  throw new RuntimeException("Table still not created");
}

Thread.sleepを使用すると、現在のスレッドがブロックされ、リソースが消費されることを理解しています。しかし、かなり中規模のアプリケーションでは、1つのスレッドが大きな問題になりますか?
ScheduledThreadPoolExecutorを使用する場所を読んで、そこでステータスポーリングを行います。ただし、ポーリングを実行する実行可能なメソッドが実行される少なくとも1つのスレッドでこのプールを初期化する必要があります。

Thread.sleepを使用する理由についての提案は、このような悪いアイデアと言われ、上記と同じことを達成するための代替オプションは何ですか。

http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

27
RandomQuestion

そのような状況でThread.sleepを使用しても構いません。人々がThread.sleepを思いとどまらせる理由は、競合状態を修正しようとする悪意のある試みで頻繁に使用され、通知ベースの同期がはるかに優れた選択である場合などに使用されるためです.

この場合、APIから通知が提供されないため、オプションはありませんがポーリングを行ってください。また、おそらく1,000個のテーブルを作成することはないので、これはまれな操作であることがわかります。

したがって、ここでThread.sleepを使用しても問題ありません。あなたが言ったように、とにかく現在のスレッドをブロックしようとしているときに別のスレッドを生成すると、メリットのないことを複雑にするようです。

34
Enno Shioji

はい、Thread.sleep(x)の使用を避けようとする必要がありますが、完全に忘れてはなりません。

なぜ避けるべきか

  • ロックを解除しません
  • 実行がスリープ時間後に開始されることを保証しません(したがって、永遠に待機し続ける可能性があります-明らかにまれなケース
  • フォアグラウンド処理スレッドを誤ってスリープ状態にすると、xミリ秒までそのアプリケーションを閉じることができなくなります。
  • 特定の問題(設計パターン(もちろん正確ではない)など)のために新しい並行性パッケージをフルロードしました。なぜThread.sleep(x)を使用するのか。

Thread.sleep(x)を使用する場所:

  • バックグラウンド実行スレッドの遅延を提供するため
  • 他の人はほとんどいません。
6
Amandeep