2017-01-19 88 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(); 

    } 
} 

輸出:爲什麼這兩個輸出有所不同?

奇線程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

即使線程2

奇Thread3

即使Thread4

奇Thread5

即使Thread6

奇Thread7

即使Thread8

奇Thread9

即使Thread10

+0

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

回答

3

擴展Thread或實施Runnable不會改變你的代碼的行爲,但一般最好使用Runnable的原因解釋here。 你顯示的兩個軟件同樣被竊聽,這只是一個巧合,第二個是返回正確的答案(我試圖在我的機器上運行,他們都返回正確的答案)。

那麼,發生了什麼?在開始時,兩個線程都處於RUNNABLE狀態,所以兩者都可以獲取固有鎖定(使用synchronization原語)。在你的情況下,奇怪的線程首先獲得它,所以即使線程在BLOCKED狀態。奇怪的線程打印他的電話號碼並通知(本例中沒有人)。在循環結束時,它釋放內部鎖並再次啓動循環。現在即使線程也不再受鎖的阻塞,所以兩個線程都可以嘗試再次獲取內部鎖:這稱爲競爭條件,這意味着輸出取決於兩個線程的執行時間。

在第一種情況下,即使主題是更快獲得鎖,但因爲flag現在是true它會在WAITING狀態,釋放所使用的奇主題打印「奇線程2」,並通知即便螺紋鎖進入BLOCKED狀態(詳情請參閱here)。在循環結束時,Odd Thread釋放鎖,我們再次處於兩個線程都可以獲取鎖的相同情況:在最壞的情況下,即使Thread可以始終先放置並保持在while循環中,等待Odd線程完成所有工作。

+0

「同樣錯誤」是非常不準確的語言,'Runnable'和'Thread'都沒有被'竊聽'。 –

+0

對不起,我的意思是上面的實現,我試圖重新編寫:) – SimoV8

+1

@RealSkeptic在開始時我以爲是相同的,但實際上它不是,因爲只有一個'EvenOddWithTwoThreads'實例被創建並傳遞給'new Thread'作爲' Runnable參考('Thread'實現'Runnable'本身),所以兩個線程在同一個對象/鎖上同步。 – SimoV8

相關問題