等待通知机制:
1、 wait()方法:使当前执行代码的线程停止,wait()方法是Object类的方法,该方法用于将当前的线程置于“预执行队列”中,并且当wait()所在的代码处停止执行,知道接到通知或被中断为止。
public class Test5_4{ public static void main(String[] args) throws InterruptedException { Object object = new Object(); synchronized (object) { System.out.println("正在等待"); object.wait(); System.out.println("等待完毕"); } System.out.println("main方法结束了"); } }
执行到object.wait()之后就一直等待下去,那么程序肯定不能一直这么等待下去了。这个时候就需要使用到 了另外一个方法唤醒的方法notify()
2、notify()方法:notify()方法也是在同步方法或者同步代码块中调用,即在调用前,线程也必须获得该对象的对象级别锁。若调用notify()时没有持有适当的锁,会抛出IllegalMonitorStateException异常。 在执行notify方法后,当前线程不会立刻释放该对象锁,呈wait状态的线程也不会立刻获得该对象锁,要等到执行notify方法的线程将程序执行完,即退出synchronized代码块后,当前线程才会释放锁,呈现wait状态所在的线程才会获得该对象锁。
//notify方法 class MyRunnable implements Runnable{ private Object object; private boolean flag; public MyRunnable(boolean flag,Object object) { super(); this.object = object; this.flag = flag; } public void waitMethod() { synchronized (object) { try { while(true) { System.out.println("wait()方法开始:"+Thread.currentThread().getName()); object.wait(); System.out.println("wait()方法结束:"+Thread.currentThread().getName()); return; } }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void notifyMethod() { synchronized (object) { try { System.out.println("notify()方法开始:"+Thread.currentThread().getName()); object.wait(); System.out.println("notify()方法结束:"+Thread.currentThread().getName()); return; }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void run() { if (flag) { this.waitMethod(); } else { this.notifyMethod(); } } } public class Test5_4{ public static void main(String[] args) throws InterruptedException { Object object = new Object(); MyRunnable waitThread = new MyRunnable(true, object); MyRunnable notifyThread = new MyRunnable(false, object); Thread thread1 = new Thread(waitThread, "wait线程"); Thread thread2 = new Thread(notifyThread, "notify线程"); thread1.start(); Thread.sleep(1000); thread2.start(); System.out.println("main方法结束!!"); } }
wait使线程停止,notify使停止的线程继续运行。且 wait,notify必须使用在synchronized同步方法或者代码块内。
生产者消费者模型:
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队 列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从 阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
//一生产一消费 class Goods{ //物品名称 private String goodName; //物品数量 private int goodNum; //生产方法 public synchronized void pro(String goodName) throws InterruptedException { //此时还有未消费的产品 if(this.goodNum > 0) { System.out.println("还有未消费产品,等待消费者中"); wait(); } this.goodName = goodName; this.goodNum = goodNum + 1; Thread.sleep(1000); System.out.println("生产"+toString()); //生产好产品后通知消费者来进行消费 notify(); } //消费方法 public synchronized void con() throws InterruptedException { if(this.goodNum == 0) { System.out.println("商品被消费完了,请稍等片刻"); wait(); } this.goodNum = goodNum -1; Thread.sleep(1000); System.out.println("消费"+toString()); //产品被消费完,通知生产者生产 notify(); } public String toString() { return "Goods [goodName = "+goodName +" , goodNum = "+goodNum + "]"; } } //消费者类 class Produce implements Runnable{ private Goods goods; public Produce(Goods goods) { super(); this.goods = goods; } public void run() { while(true) { try { this.goods.pro("小轿车"); } catch (InterruptedException e) { e.printStackTrace(); } } } } //生产者类 class Consumer implements Runnable{ private Goods goods; public Consumer(Goods goods) { super(); this.goods = goods; } public void run() { while(true) { try { this.goods.con(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Test5_4{ public static void main(String[] args) throws InterruptedException { Goods goods = new Goods(); Produce produce = new Produce(goods); Consumer consumer = new Consumer(goods); Thread produceThread = new Thread(produce,"生产者线程"); Thread consumerThread = new Thread(consumer,"消费者线程"); consumerThread.start(); Thread.sleep(1000); produceThread.start(); } }