多執行緒中的wait與notify

pucheung發表於2015-03-29
wait(),notify(),notifyAll()不屬於Thread類,而是屬於Object基礎類,也就是說每個對像都有wait(),notify(),notifyAll()的功能.因為都個對像都有鎖,鎖是每個對像的基礎,當然操作鎖的方法也是最基礎了。
   wait導致當前的執行緒等待,直到其他執行緒呼叫此物件的 notify() 方法或 notifyAll() 方法,或被其他執行緒中斷。wait只能由持有對像鎖的執行緒來呼叫。
 notify喚醒在此物件監視器上等待的單個執行緒。如果所有執行緒都在此物件上等待,則會選擇喚醒其中一個執行緒(隨機)。直到當前的執行緒放棄此物件上的鎖,才能繼續執行被喚醒的執行緒。同Wait方法一樣,notify只能由持有對像鎖的執行緒來呼叫.notifyall也一樣,不同的是notifyall會喚配所有在此物件鎖上等待的執行緒。
"只能由持有對像鎖的執行緒來呼叫"說明wait方法與notify方法必須在同步塊內執行,即synchronized(obj)之內.再者synchronized程式碼塊內沒有鎖是寸步不行的,所以執行緒要繼續執行必須獲得鎖。相輔相成。
  在哪個物件上wait就應該在哪個物件上notify,也就是說wait與notify必須作用在同一個物件上。
看一個很經典的例子(生產者與消費者):

package ProductAndConsume; 
import java.util.List; 

public class Consume implements Runnable{ 
        private List container = null
        private int count; 
        public Consume(List lst){ 
            this.container = lst; 

public void run() { 
     
    while(true){ 
     synchronized (container) { 
        if(container.size()== 0){ 
         try { 
            container.wait();//容器為空,放棄鎖,等待生產 
         } catch (InterruptedException e) { 
            e.printStackTrace(); 
         } 
        } 
        try { 
         Thread.sleep(100); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        container.remove(0); 
        container.notify(); 
        System.out.println("我吃了"+(++count)+"個"); 
     } 
    } 
     




package ProductAndConsume; 
import java.util.List; 

public class Product implements Runnable { 
private List container = null
        private int count; 
public Product(List lst) { 
    this.container = lst; 


public void run() { 
    while (true) { 
     synchronized (container) { 
        if (container.size() > MultiThread.MAX) { 
         //如果容器超過了最大值,就不要在生產了,等待消費 
         try { 
            container.wait(); 
         } catch (InterruptedException e) { 
            e.printStackTrace(); 
         } 
        } 
        try { 
         Thread.sleep(100); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        container.add(new Object()); 
        container.notify(); 
        System.out.println("我生產了"+(++count)+"個"); 
     } 
    } 





package ProductAndConsume; 
import java.util.ArrayList; 
import java.util.List; 

public class MultiThread { 
private List container = new ArrayList(); 
public final static int MAX = 5; 
public static void main(String args[]){ 

MultiThread m = new MultiThread(); 

    new Thread(new Consume(m.getContainer())).start(); 
    new Thread(new Product(m.getContainer())).start(); 
    new Thread(new Consume(m.getContainer())).start(); 
    new Thread(new Product(m.getContainer())).start(); 

public List getContainer() { 
    return container; 


public void setContainer(List container) { 
    this.container = container; 
}

相關文章