现在的位置: 首页 > 综合 > 正文

java 多线程之 wait(),notify(),notifyAll()以及经典的生产者消费者模型

2014年10月25日 ⁄ 综合 ⁄ 共 2826字 ⁄ 字号 评论关闭

http://www.cnblogs.com/anran_guojianjun/archive/2009/04/14/1435278.html

      wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()
的功能.因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了.
      先看java doc怎么说:
      wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.

      notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由作为此对象监视器的所有者的线程来调用.

"当前的线程必须拥有此对象监视器"与"此方法只应由作为此对象监视器的所有者的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj之内).

      调用对像wait方法后,当前线程释放对像锁,进入等待状态.直到其他线程(也只能是其他线程)通过notify 方法,或 notifyAll.该线程重新获得对像锁继续执行,记得线程必须重新获得对像锁才能继续执行。因为synchronized代码块内没有锁是寸步不能走的。看一个很经典的例子; 

  1. package ProductAndConsume;  
  2. import java.util.List;  
  3. public class Consume implements Runnable{  
  4.     private List container = null;  
  5.     private int count;  
  6.     public Consume(List lst){  
  7.      this.container = lst;  
  8.     }  
  9.  public void run() {  
  10.     
  11.   while(true){  
  12.    synchronized (container) {  
  13.     if(container.size()== 0){  
  14.      try {  
  15.       container.wait();//放弃锁  
  16.      } catch (InterruptedException e) {  
  17.       e.printStackTrace();  
  18.      }  
  19.     }  
  20.     try {  
  21.      Thread.sleep(100);  
  22.     } catch (InterruptedException e) {  
  23.      // TODO Auto-generated catch block  
  24.      e.printStackTrace();  
  25.     }  
  26.     container.remove(0);  
  27.     container.notify();  
  28.     System.out.println("我吃了"+(++count)+"个");  
  29.    }  
  30.   }  
  31.     
  32.  }  
  33. }  
  34. package ProductAndConsume;  
  35. import java.util.List;  
  36. public class Product implements Runnable {  
  37.  private List container = null;  
  38.     private int count;  
  39.  public Product(List lst) {  
  40.   this.container = lst;  
  41.  }  
  42.  public void run() {  
  43.   while (true) {  
  44.    synchronized (container) {  
  45.     if (container.size() > MultiThread.MAX) {  
  46.      try {  
  47.       container.wait();  
  48.      } catch (InterruptedException e) {  
  49.       e.printStackTrace();  
  50.      }  
  51.     }  
  52.     try {  
  53.      Thread.sleep(100);  
  54.     } catch (InterruptedException e) {  
  55.      e.printStackTrace();  
  56.     }  
  57.     container.add(new Object());  
  58.     container.notify();  
  59.     System.out.println("我生产了"+(++count)+"个");  
  60.    }  
  61.   }  
  62.  }  
  63. }  
  64. package ProductAndConsume;  
  65. import java.util.ArrayList;  
  66. import java.util.List;  
  67. public class MultiThread {  
  68.  private List container = new ArrayList();  
  69.  public final static int MAX = 5;  
  70.   
  71.   public static void main(String args[]){  
  72.  MultiThread m = new MultiThread();  
  73.   new Thread(new Consume(m.getContainer())).start();  
  74.   new Thread(new Product(m.getContainer())).start();  
  75.   new Thread(new Consume(m.getContainer())).start();  
  76.   new Thread(new Product(m.getContainer())).start();  
  77.  }  
  78.  public List getContainer() {  
  79.   return container;  
  80.  }  
  81.  public void setContainer(List container) {  
  82.   this.container = container;  
  83.  }  

代码中让线程sleep仅仅是为了减慢线程的执行速度。让你看的更清楚。

抱歉!评论已关闭.