1.线程间通信
2.等待唤醒机制
3.等待唤醒案例
3.1简单生产者消费者案例
分析:
代码:
Object类中的方法
void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void notify() 唤醒正在等待对象监视器的单个线程。
package com.goldencis.thread; /** * 等待唤醒案例 :线程之间的通信 * 创建一个顾客进程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入waiting状态(无限等待) * 创建一个老板进程(生产者):花费5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子 * * 注意: * 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只有一个在执行 * 同步使用的锁对象必须保证唯一 * 只有锁对象才能调用wait和notify方法 * * Object类中的方法 * void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。 * void notify() 唤醒正在等待对象监视器的单个线程。 */ public class DemoWaitAndNotify { public static void main(String[] args) { //锁对象 Object obj = new Object(); //创建一个顾客进程(消费者) new Thread(){ @Override public void run() { synchronized (obj){ while(true){ //告知老板要的包子的种类和数量 System.out.println("告知老板要的包子的种类和数量"); //调用wait方法,放弃cpu的执行,进入waiting状态(无限等待) try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("吃包子咯"); } } } }.start(); //创建一个老板进程(生产者) new Thread(){ //做好包子之后,调用notify方法,唤醒顾客吃包子 @Override public void run() { while(true){ //花费5秒做包子, try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj){ System.out.println("老板花费5秒做包子,唤醒顾客吃包子"); obj.notify(); } } } }.start(); } }
进入计时等待有两种方式:
sleep(long m) 在毫秒值结束之后,线程睡醒进入Runnable/Blocked状态wait(long m) 如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入Runnable/Blocked状态
唤醒方式:
notify() 唤醒正在等待对象监视器的单个线程notifyAll() 唤醒正在等待对象监视器的所有线程
3.2 生产者与消费者案例
分析:
代码:
包子类Bun.java
package com.goldencis.thread.BunPAC; /** * 包子类 */ public class Bun { String pi; String xian; boolean flag;//包子资源是否存在 public String getPi() { return pi; } public void setPi(String pi) { this.pi = pi; } public String getXian() { return xian; } public void setXian(String xian) { this.xian = xian; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }
生产者Producer.java
package com.goldencis.thread.BunPAC; /** * 生产者 */ public class Producer extends Thread{ private Bun bun;//包子 private Object obj;//锁对象 public Producer(Bun bun, Object obj) { this.bun = bun; this.obj = obj; } @Override public void run() { while(true){ synchronized (obj){ //没有包子,生产包子 if(bun.flag == false){ try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("包子铺生产了一个包子"); bun.flag = true; obj.notify();//唤醒消费者 // 有包子,等待 }else{ try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Consumer.java
package com.goldencis.thread.BunPAC; /** * 消费者 */ public class Consumer extends Thread{ private Bun bun;//包子 private Object obj;//锁对象 public Consumer(Bun bun, Object obj) { this.bun = bun; this.obj = obj; } @Override public void run() { while (true){ synchronized (obj){ //有包子,吃包子 if(bun.flag == true){ System.out.println("吃包子咯"); bun.flag = false; obj.notify();//唤醒生产者 //没有包子,等待 }else{ try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
测试类Test.java
package com.goldencis.thread.BunPAC; public class Test { public static void main(String[] args) { Bun bun =new Bun(); bun.setFlag(false); Object obj = new Object(); Producer p = new Producer(bun,obj); Consumer c = new Consumer(bun,obj); p.start(); c.start(); } }
注:可以把包子(bun)作为锁对象,就不用创建Object对象了