2011-09-10 7 views
2

私はラジオをJavaでコーディングしており、もちろんストリームを再生するためにスレッドを使用しています。スレッドのrunメソッドでshouldPlayという変数がtrueであるかどうかをチェックしていますプレーヤーを実行します。次に、変数をfalseに設定するpause()メソッドがあります。変数がfalseのときに自然にプレーヤを実行しないようにします。スレッド内のこのJavaループはなぜ機能しませんか?

class audiostream extends Thread { 

    private boolean shouldPlay = true; 

    @Override 
    public void run() { 
     while(true) 
     { 
      if(shouldPlay) 
      { 
       shouldPlay = false; 
       System.out.print("test"); 
      } 
     } 
    } 

    public void pause() { 
     shouldPlay = false; 
    } 

    public void play() { 
     shouldPlay = true; 
    } 

} 

スレッドが最初に実行したときに何が起こるしたいことはあるが、それは(それがうまくありません)「test」を印刷する必要があります:私は、私は以下のことを設定したかの小さな例を作成しました。次にpause()を実行するとshouldPlayがfalseに設定され、 "test"が出力されなくなります。しかし、play()を呼び出すとshouldPlayがtrueに設定され、テストが再び印刷されます。問題はそれがこれをしていないということです。

時間の約1/100です。親スレッドを「ハング」しないように別のスレッドからplay()とpause()を呼び出し、私の子スレッドがwhileループでハングしていて、play()または親からpause()を呼び出すと、そのループのために変数は値を変更しませんか?それが事実なら、私は何をすべきか分からない!

答えて

4

追加 '揮発性' が

private volatile boolean shouldPlay = true; 
1

shouldPlayvolatileする必要があります修正し、削除してくださいます - shouldPlay = false;は、

if(shouldPlay) 
{ 
    // shouldPlay = false; 
     System.out.print("test"); 
} 
1

あなたは代替としてAtomicBooleanを利用することができます。

0

Javaメモリモデルでは、が同期化されていれば、他のスレッドが行った変更をスレッドで確認できます()。 Java言語仕様definesが同期-で次のように:

同期アクションが同期-で次のように定義されたアクション、上の関係誘導

  • モニターmのロック解除アクションが同期-とをm(以後は同期順序に従って定義されます)のすべての以降のロックアクション。
  • vは、とすべてのスレッド(後で同期順序に従って定義されます)によってvのすべての後続の読み取りと同期します。
  • スレッドを開始するアクションは、起動するスレッドの最初のアクションであると同期します。
  • 各変数へのデフォルト値(ゼロ、偽またはヌル)の書き込みは、各スレッドの最初のアクションであると同期します。変数を含むオブジェクトが割り当てられる前に変数にデフォルト値を書き込むのはちょっと奇妙に思えるかもしれませんが、概念的にはすべてのオブジェクトはプログラムの開始時にデフォルトの初期化された値で作成されます。
  • スレッドの最後のアクションT1は、T1が終了したことを検出する別のスレッドT2のアクションをと同期させます。T2T1.isAlive()またはT1.join()を呼び出すことでこれを達成できます。
  • スレッドT1スレッドT2を中断した場合、T1による割り込みが同期-と他のスレッドが(T2を含む)の任意の点はT2は(スローInterruptedExceptionを有することによって、またはThread.interrupted又はThread.isInterruptedを呼び出すことによって)中断されたと判断します。あなたの例では

は、スレッドの書き込みshouldPlayと、それはそれのどれもしない読んでスレッドが、それによってsynchronized-withを確立することができません。したがって、読取りスレッドが新しい値に気づくかどうかがわかっていれば、それは不特定である。

場合によっては、shouldPlayvolatileを宣言すると、その同期を確立する最も簡単な方法です。

関連する問題