主要是如何使用wait notify/notifyAll
先定义生产和消费的方法(同步问题)
public class Storage { /** * 仓库最大容量 */ private static int MAX_VALUE = 100; /** * 储存产品 */ private List<Object> list = new ArrayList<>(); /** * 生产num个产品 * @param num */ public void produce(int num) { synchronized (list) { //一定是while,因为wait被唤醒后需要判断是不是满足生产条件;仓库剩余的容量不足以存放即将要生产的数量,暂停生产;要注意,notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。所以在进行条件判断时候,可以先把 wait 语句忽略不计来进行考虑,显然,要确保程序一定要执行,并且要保证程序直到满足一定的条件再执行,要使用while来执行,以确保条件满足和一定执行 while (list.size() + num > MAX_VALUE) { System.out.println("暂时不能执行生产任务"); try { //条件不满足,生产阻塞,会释放当前的锁,然后让出CPU,进入等待状态 list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //满足条件后开始生产 for (int i = 0; i < num; i++) { list.add(new Object()); } System.out.println("已生产产品数"+num+" 仓库容量"+list.size()); //只有当 notify/notifyAll() 被执行时候,才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。 list.notifyAll(); } } /** * 消费num个产品 * @param num */ public void consume(int num) { synchronized (list) { while (list.size() < num) { System.out.println("暂时不能执行消费任务"); try { list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //满足条件后开始消费 for (int i = 0; i < num; i++) { list.remove(0); } System.out.println("已消费产品数"+num+" 仓库容量" + list.size()); list.notifyAll(); } } }
定义生产者线程
public class Producer extends Thread { /** * 生产产品个数 */ private int num; private Storage storage; public Producer(Storage storage) { this.storage = storage; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public void run() { storage.produce(getNum()); } }
定义消费者线程
public class Customer extends Thread { /** * 消费产品个数 */ private int num; private Storage storage; public Customer(Storage storage) { this.storage = storage; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public void run() { storage.consume(getNum()); } }
最后写一个测试类,用来开启多个生产者,消费者线程执行操作
public class Test { public static void main(String[] args) { Storage storage = new Storage(); Producer p1 = new Producer(storage); Producer p2 = new Producer(storage); Producer p3 = new Producer(storage); Producer p4 = new Producer(storage); Customer c1 = new Customer(storage); Customer c2 = new Customer(storage); Customer c3 = new Customer(storage); p1.setNum(10); p2.setNum(20); p3.setNum(10); p4.setNum(80); c1.setNum(50); c2.setNum(20); c3.setNum(20); c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); p4.start(); } }
运行得到的结果为:
暂时不能执行消费任务
暂时不能执行消费任务
暂时不能执行消费任务
已生产产品数10 仓库容量10
暂时不能执行消费任务
暂时不能执行消费任务
已生产产品数20 仓库容量30
已生产产品数10 仓库容量40
暂时不能执行生产任务
暂时不能执行消费任务
已消费产品数20 仓库容量20
已消费产品数20 仓库容量0
暂时不能执行消费任务
已生产产品数80 仓库容量80
已消费产品数50 仓库容量30
核心的就是每个线程拿到锁之后检测是不是满足条件,不满足则wait释放锁及CPU资源,等待被唤醒之后判断条件满足的话执行生产/消费操作,然后唤醒别的等待的线程,此线程结束