2013-09-26 12 views
31

それを変更します。待ち、私はこのように変更するブール値を待つスレッドを持っている状態

ブール値が状態を変更するまで、スレッドをブロックする方法はありますか?あなたがビジー待機を避ける仕組みが必要いかがwait-notify

private Boolean bool = true; 
private final Object lock = new Object(); 

private Boolean getChange(){ 
    synchronized(lock){ 
    while (bool) { 
     bool.wait(); 
    } 
    } 
    return bool; 
} 
public void setChange(){ 
    synchronized(lock){ 
     bool = false; 
     bool.notify(); 
    } 
} 

答えて

58

大量のCPU消費が原因でこれを行うのは私の好みの方法ではありません。

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

実際の問題は、値をチェックするスレッドは、キャッシングのために任意の時間が経過しても変更が反映されないことがあることです。値は常に、スレッド間で同期されていることを確認するには、変数の定義でvolatileキーワードを配置する必要があり、すなわち

private volatile boolean value; 

注このような通知ベースのソリューションを使用するときのように、​​ブロックにアクセスを置くこと他の回答に記載されているように、同じ効果があります。

+4

"揮発性"を示唆しています... – TheLostMind

7

。古いwait/notifyメカニズムはそう例えば、java.util.concurrentライブラリからCountDownLatchを何かを好む落とし穴をはらんでいる:

public final CountDownLatch latch = new CountDownLatch(1); 

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

。しかし、他の側のコール

yourRunnableObj.latch.countDown(); 

で、何もしないために、スレッドを開始するが、それが必要になるまで待って、まだ最善の方法ではありません。 ExecutorServiceを採用することもできます。ExecutorServiceには、条件が満たされたときに実行する必要がある作業をタスクとして送信します。

+7

'bool'は可変フィールドですが、同期することはできません。 – axtavt

+0

umm ...それは実際には実行可能なPoint @axtavtです。 –

+0

これで、非最終フィールドで同期しています。 'setChange'では、まずそれを変更し、新しい' false'インスタンスに通知します。結果:以前の 'true'インスタンスを待機しているスレッドは決して通知されません。このメカニズム全体を避ける*のもう一つの素晴らしい例です。 –

34

+0

これは、JUnit内のQuartzライブラリのテストに役立ちます。 Quartzは独自のスレッドプールを持つブラックボックスでジョブを実行します。私は、JUnitに、javaのドキュメントで指定されている正確なパターンを使用してクォーツジョブが完了するのを待つように指示できます。 –

+0

'Java.util.concurrent.BlockingQueue'とそのさまざまな実装を提案できますか? 'take()'と 'offer()'メソッドは、同期のための素晴らしい出発点です。 – Groostav

1

私はこのような場合にmutexメカニズムを使用することをお勧めしますが、実際にブール値を使用する場合は、volatile(スレッド間で変更の可視性を提供する)として宣言し、条件として:

//.....some class 

volatile boolean someBoolean; 

Thread someThread = new Thread() { 

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

}; 
+15

これはCPUを噛んでいませんか? –

2

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

Integer any = new Integer(0); 

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

public synchronized void change() { 
    any.notify(); 
} 
+2

整数は不変ですが、値を変更することはできません – Andrejs

関連する問題