2017-01-19 11 views
3
public class EvenOddWithTwoThreads **extends Thread** 
{ 
private volatile int count = 1; 
private volatile boolean flag = false; 
@Override 
public void run() { 
    while(count <=10){ 
     synchronized (this) { 
      while(flag){ 
       flag= false; 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(Thread.currentThread().getName() +count); 
      count= count+1; 
      flag = true; 

      notify(); 
     } 
    } 
} 

public static void main(String[] args) { 

    EvenOddWithTwoThreads ins = new EvenOddWithTwoThreads(); 
    **Thread t1 = new Thread(ins, "Odd Thread");** 
    **Thread t2 = new Thread(ins,"Even Thread");** 

    t1.start(); 
    t2.start(); 

    } 
} 

出力:なぜ2つの出力が異なるのですか?

奇数スレッド1

奇数スレッド2

奇数Thread3

でもThread4

奇数Thread5

でもThread6

奇数Thread7

でもThread8

奇数Thread9

でもThread10

public class EvenOddWithTwoThreads **implements Runnable**{ 

private volatile int count = 1; 
private volatile boolean flag = false; 


@Override 
public void run() { 
    while(count <=10){ 
     synchronized (this) { 
      while(flag){ 
       flag= false; 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(Thread.currentThread().getName() +count); 
      count= count+1; 
      flag = true; 

      notify(); 
     } 
    } 
} 

public static void main(String[] args) { 

    EvenOddWithTwoThreads ins = new EvenOddWithTwoThreads(); 
    Thread t1 = new Thread(ins, "Odd Thread"); 
    Thread t2 = new Thread(ins,"Even Thread"); 

    t1.start(); 
    t2.start(); 

    } 
} 

出力:

奇数スレッド1

でもThread4

でもThread6

奇数Thread7

でもThread8奇数Thread5

でもスレッド2

奇数Thread3

奇数Thread9

でもThread10

+0

check [this](http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread) – Null

答えて

3

Threadを拡張するか、Runnableはあなたのコードの動作を変更しませんが、一般的に、それはhereを説明された理由Runnableを使用することをお勧めします実装。 あなたが見せた2つのソフトウェアは同じように盗聴されています.2番目のものが正解を返すのは偶然のことです(私は自分のマシンで実行しようとしました。

何が起こっているのですか?最初は両方のスレッドがRUNNABLEの状態になっているため、どちらも組み込みロック(synchronizationプリミティブ)を取得できます。あなたの場合、奇妙なスレッドが最初にそれを取得するので、偶数スレッドはに入ります。ブロックの状態になります。奇妙なスレッド彼の番号を印刷し、通知する(この場合は誰もいない)。ループの最後に、固有のロックが解除され、ループが再び開始されます。 Now Even Threadはロックによってブロックされなくなるため、両方のスレッドが再度固有ロックを取得しようとする可能性があります。これは競合条件と呼ばれ、出力は2つのスレッドの実行タイミングに依存します。最初のケースであってもスレッドが高速で、ロックを取得、しかしflagがtrueになりましたので、それは「奇数スレッド2」を印刷してでもスレッドを通知するために、奇数のスレッドによって使用されているロックを解除、状態を待ちに行くに

BLOCKED州(詳細はhereを参照してください)。ループが終了すると、Odd Threadがロックを解除し、両方のスレッドがロックを取得できる同じ状況になります。最悪の場合のシナリオでも、Even Threadは常に最初に進み、whileループにトラップされて、Oddスレッドはすべての仕事をします。

+0

「等しく盗んだ」とは非常に不正確な言語であり、 'Runnable'も' Thread'も「盗聴されていません」。 –

+0

申し訳ありませんが、私は上記の実装を意味していました。私は言い換えようとしています:) – SimoV8

+1

@RealSkeptic最初は同じではありましたが、実際はそうではありません。 'EvenOddWithTwoThreads'のインスタンスが1つしか作成されず、' new Thread' Runnable'参照( 'Thread'は' Runnable'自体を実装しています)ので、2つのスレッドは同じオブジェクト/ロックで同期します。 – SimoV8

関連する問題