54

次のようにブール値が変化するのを待つスレッドがあります。

while(!value)
{
  Thread.sleep(1000)
}
// Do some work after change of the value

これは、大量の CPU 消費の原因となるため、私が好む方法ではありません。

ブール値が状態を変えるまで、スレッドをブロックする方法はありますか?

4

6 に答える 6

86

これは、大量の CPU 消費の原因となるため、私が好む方法ではありません。

それが実際に機能するコードである場合は、そのままにしておいてください。ブール値を 1 秒に 1 回チェックしても、測定可能な CPU 負荷は発生しません。何もありません。

本当の問題は、値をチェックするスレッドが、キャッシングのために任意に長い間発生した変更を認識できない可能性があることです。値がスレッド間で常に同期されるようにするには、変数定義に volatile キーワードを入れる必要があります。

private volatile boolean value;

synchronized他の回答で説明されている通知ベースのソリューションを使用する場合など、アクセスをブロックに入れると同じ効果があることに注意してください。

于 2013-09-26T10:23:23.507 に答える
59

ビジー待機を回避するメカニズムが必要です。古いwait/notifyメカニズムには落とし穴がたくさんあるので、次のようなjava.util.concurrentライブラリの何かを優先してCountDownLatchください:

public final CountDownLatch latch = new CountDownLatch(1);

public void run () {
  latch.await();
  ...
}

そして向こう側の電話で

yourRunnableObj.latch.countDown();

ただし、必要になるまで待機するだけでスレッドを開始することは、依然として最善の方法ではありません。ExecutorService条件が満たされたときに実行する必要がある作業をタスクとしてサブミットする を使用することもできます。

于 2013-09-26T10:22:46.723 に答える
2

わかりました多分これはあなたの問題を解決するはずです。変更を行うたびに、待機を解放する change() メソッドを呼び出すことに注意してください。

Integer any = new Integer(0);

public synchronized boolean waitTillChange() {
    any.wait();
    return true;
}

public synchronized void change() {
    any.notify();
}
于 2013-09-26T10:30:27.073 に答える
0

私はそのような場合にミューテックスメカニズムを使用することを好みますが、本当にブール値を使用したい場合は、(スレッド間で変更の可視性を提供するために) 揮発性として宣言し、そのブール値を条件としてボディレスサイクルを実行する必要があります:

//.....some class

volatile boolean someBoolean; 

Thread someThread = new Thread() {

    @Override 
    public void run() {
        //some actions
        while (!someBoolean); //wait for condition 
        //some actions 
    }

};
于 2013-09-26T10:25:40.310 に答える