web-dev-qa-db-ja.com

whileループ内のThread.sleep()

Javaコード内のwhileループでThread.sleep()を使用することについてNetBeansが警告していることに気づきました。そのため、この問題についていくつか調査しました。主に問題は1つだと思われますカウンタがまだスリープしている間にwhile条件がtrueになる可能性があるため、次の反復を待機するときに壁時計の時間を浪費することになります。

私のアプリケーションは、リモートシステムに接続し、操作の状態を定期的にポーリングして、操作が完了するまで待機してから次のリクエストを送信する必要があります。現時点では、コードはこれを論理的に実行します。

String state = get state via RPC call
while (!state.equals("complete")) {
    Thread.sleep(10000); // Wait 10 seconds
    state = {update state via RPC call}
}

状況がリモート操作をチェックしていることを考えると(これは数秒間実行されるため、多少コストのかかるプロセスです)、whileループでのThread.sleep()の有効な使用ですか?このロジックを構造化するより良い方法はありますか? Timerクラスを使用できるいくつかの例を見てきましたが、上記と同じ単純なロジックに煮詰められているように見えますが、はるかに複雑な点が含まれているため、メリットはわかりません。

この場合のリモートシステムは、私の直接の制御下にも、Javaで記述されているわけでもないため、このシナリオでその目的をより「協調的」に変更することはオプションではありません。アプリケーションの状態の値を更新する唯一の方法は、XMLメッセージを作成して送信し、応答を受信して​​解析し、必要な情報を抽出することです。

どんな提案やコメントも大歓迎です。

21
Steve Ferguson

リモートシステムがイベントを発行したり、非同期で通知したりできない場合を除いて、上記はまったく無理ではないと思います。 sleep()の時間とRPC呼び出しが行う時間/負荷のバランスをとる必要がありますが、それが唯一の問題であり、上記はまったく問題ではないようです。

13
Brian Agnew

リモートエンドを変更して、長期実行プロセスで実行されたことを示す「プッシュ」通知を提供することができなければ、それはほぼ可能です。 Thread.sleep時間がポーリングのコストと比較して長い限り、問題はありません。

4

睡眠は非常に非効率的であり、良い習慣ではないので、(ほとんど)決して使用しないでください。スレッドが互いに信号を送る場所では、常にロックと条件変数を使用してください。 Mike Dahlinの スレッドを使用したプログラミングのコーディング標準を参照してください

テンプレートは次のとおりです。

public class Foo{
  private Lock lock;
  private Condition c1;
  private Condition c2;

  public Foo()
  {
    lock = new SimpleLock();
    c1 = lock.newCondition();
    c2 = lock.newCondition();
    ...
  }

  public void doIt()
  {
    try{
      lock.lock();
      ...
      while(...){
        c1.awaitUninterruptibly();
      }
      ...
      c2.signal();
    }
    finally{
      lock.unlock();
    }
  }
}
0
Cemre