2014-12-23 77 views
2

當我運行這段代碼,它會顯示以下輸出:掛起恢復線程:Java的

One : 15 Two : 15 One : 14 Two : 14 Two : 13 One : 13 Two : 12 One : 12 One : 11 Two : 11 Thread 1 suspended Two : 10 Two : 9 Two : 8 Two : 7 Two : 6 Thread 1 resumed Thread 2 suspended Thread 2 resumed

輸出不繼續到那是 一結束:1 二:1 是NewThread1類的方法不執行?這背後的原因是什麼?

以下是NewThread1的代碼:繼

class NewThread1 implements Runnable{ 
String name; 
Thread t; 
boolean suspendFlag; 

NewThread1(String threadname){ 
    name = threadname; 
    t = new Thread(this, name); 
    suspendFlag = false; 
    t.start(); 
} 

@Override 
public void run(){ 
    try{ 
     for(int i=15; i>0; i--){ 
      System.out.println(name+ " : " +i); 
      Thread.sleep(200); 
       synchronized(this){ 
        while(suspendFlag){ 
         wait(); 
        } 
       } 
     } 
    }catch(InterruptedException e){ 
     System.out.println("New thread1 Interrupted"); 
    } 
} 
synchronized void myresume(){ 
    suspendFlag = false; 
} 
void mysuspend(){ 
    suspendFlag = true; 
} 
}   

是NewThread1的代碼(main()方法在這裏被定義)

public class Suspend_ResumeThreads { 
public static void main(String args[]){ 
    NewThread1 ob1 = new NewThread1("One "); 
    NewThread1 ob2 = new NewThread1("Two "); 

    try{ 
     Thread.sleep(1000); 
     ob1.mysuspend(); 
     System.out.println("Thread 1 suspended"); 
     Thread.sleep(1000); 
     ob1.myresume(); 
     System.out.println("Thread 1 resumed"); 

     ob2.mysuspend(); 
     System.out.println("Thread 2 suspended"); 
     Thread.sleep(1000); 
     ob2.myresume(); 
     System.out.println("Thread 2 resumed"); 

    }catch(InterruptedException e){ 
     System.out.println("Main Interrupted"); 
    } 

    try{ 
     ob1.t.join(); 
     ob2.t.join(); 
    }catch(InterruptedException e){ 
     System.out.println("Main interrupeted in join()"); 
    } 
System.out.println("Main exiting..");  
} 
} 
+1

您必須在同一個對象上調用'.notify()來喚醒掛在'.wait()'中的線程。 –

+0

當您使用notify/wait時,應始終將其與狀態更改關聯。當沒有任何東西在等待時,Notify()可能會發生,並且這會丟失,並且wait()可能會虛假地喚醒。 –

+0

也將'suspendFlag'標記爲volatile。或者在'synchronized'部分改變它 – talex

回答

5

使用notifyAll中斷一個wait():把

this.notifyAll(); 

納入您的myresume()功能。但總是準備好這個通知迷路;特別是當沒有線程正在等待時,它仍然會成功。

充分利用相同對象務必synchronize/wait/notify。一個常見的錯誤是在this上同步,但沒有意識到在匿名內部類的情況下,this可能會有所不同。更糟糕的是,它可以在重構代碼時改變!最佳做法是在某個地方使用Object lock = new Object();,並始終使用synchronize(lock) ... lock.wait(); ... lock.notifyAll();以避免此類編程(和重構)錯誤。

除非你做suspendFlagvolatile,也有一個機會,不同的線程看到該字段的值不同(如果不是volatile,線程可以保持在CPU高速緩存的本地副本)。因此,也可以使mysuspend同步。

在某些情況下,您可能需要切換到更高級的同步,例如 java.util.concurrent.locks.Lockjava.util.concurrent.Semaphore