java多线程等待唤醒机制
一. 方法介绍
方法 | 说明 |
---|---|
void wait() | 线程等待,等待的过程中线程会释放锁,需要被其他线程调用notify方法将其唤醒,重新抢锁执行 |
void notify() | 线程唤醒,一次唤醒一个等待线程;如果有多条线程等待,则随机唤醒一条等待线程 |
void notifyAll() | 唤醒所有等待线程 |
二.等待唤醒案例分析(线程之间的通信)
要求:一个线程生产,一个线程消费,不能连续生产,不能连续消费 -> 等待唤醒机制(生产者,消费者)(线程之间的通信)
这里一包子铺与消费者之间关系举列
1. 生产者(包子铺)
包子铺负责生产包子
那么如何表示包子铺 --> 我们这里可以定义一个count变量 , 代表生产包子的数目 , 每次生产count++
2. 消费者
消费者负责消费包子 , 每次消费的过程中只需要打印消费了第多少个包子即可
3. 生产者与消费者的关系
问1. 那么我们如何来表示现在是否存在包子 , 是需要生产还是消费?
这里只需要再定义一个标识符flag , 用于判断即可 , 当flag为true则有包子调用生产者 , 反之调用消费者
问2. 我们该如何保证在生产到一半的时候 , cpu自动切换到消费?
很简单使用线程锁即可
问3. 如何保证生产一个 , 消费一个?
即使加锁我们也无法保证生产和消费同步
这里我们就需要使用到等待和唤醒方法了
三. 代码阐述
-
创建包子铺类
在该类中我们需要对getCount和setCount进行修改 , 使其对应成为消费和生产方法
/* count和flag可以定义成包装类 但是要记得给count和flag手动赋值 不然对于本案例来说,容易出现空指针异常 */ public class BaoZiPu { //代表包子的count private int count; //代表是否有包子的flag private boolean flag; public BaoZiPu() { } public BaoZiPu(int count, boolean flag) { this.count = count; this.flag = flag; } /* getCount 改造成消费包子方法 直接输出count */ public void getCount() { System.out.println("消费了..............第"+count+"个包子"); } /* setCount 改造成生产包子 count++ */ public void setCount() { count++; System.out.println("生产了...第"+count+"个包子"); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }
-
定义生产者类
生产线程 , 在循环中通过判断flag来决定是否生产 . 如果flag为true则已有包子不需要生产 , 设置该线程等待即可 , 反之没有包子则生产 , count+1 , 将flag改为false , 并唤醒消费线程
public class Product implements Runnable{ private BaoZiPu baoZiPu; public Product(BaoZiPu baoZiPu) { this.baoZiPu = baoZiPu; } @Override public void run() { while(true){ try { Thread.sleep(100L); } catch (InterruptedException e) { throw new RuntimeException(e); } synchronized (baoZiPu){ //1.判断flag是否为true,如果是true,证明有包子,生产线程等待 if (baoZiPu.isFlag()==true){ try { baoZiPu.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } //2.如果flag为false,证明没有包子,开始生产 baoZiPu.setCount(); //3.改变flag状态,为true,证明生产完了,有包子了 baoZiPu.setFlag(true); //4.唤醒消费线程 baoZiPu.notify(); } } } }
-
消费者类
逻辑和生产者类似就不过多赘述
public class Consumer implements Runnable{ private BaoZiPu baoZiPu; public Consumer(BaoZiPu baoZiPu) { this.baoZiPu = baoZiPu; } @Override public void run() { while(true){ try { Thread.sleep(100L); } catch (InterruptedException e) { throw new RuntimeException(e); } synchronized (baoZiPu){ //1.判断flag是否为false,如果是false,证明没有包子,消费线程等待 if (baoZiPu.isFlag()==false){ try { baoZiPu.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } //2.如果flag为true,证明有包子,开始消费 baoZiPu.getCount(); //3.改变flag状态,为false,证明消费完了,没 有包子了 baoZiPu.setFlag(false); //4.唤醒生产线程 baoZiPu.notify(); } } } }
-
实现类
public class Test01 { public static void main(String[] args) { BaoZiPu baoZiPu = new BaoZiPu(); Product product = new Product(baoZiPu); Consumer consumer = new Consumer(baoZiPu); Thread t1 = new Thread(product); Thread t2 = new Thread(consumer); t1.start(); t2.start(); } }