生产者/消费者 - synchronized,condition
一、今天用synchronized实现了下生产者/消费者模式,遇到几个小问题,记录下。
public class SynchronizedDemo { //类似包子铺场景:包子最多提前做好50个,卖出去5个就再做;卖完了,买包子的就得等着 //Synchronized版本 private static int MAX = 50; private int number = 0; public void produce() throws InterruptedException { while (true) { synchronized (this) { if (number == MAX) { //释放锁,出让cpu时间片,线程状态 - WAITING,等待唤醒 this.wait(); continue; } number++; System.out.println("+++++第 " + number + " 个包子被做出来了! - " + Thread.currentThread().getName()); if (number > 20) { //做出包子超过20个,买包子的赶紧买 this.notifyAll(); } } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { if (number == 0) { //释放锁,出让cpu时间片,线程状态 - WAITING,等待唤醒 this.wait(); continue; } System.out.println("-----第 " + number + "个包子被买了! - " + Thread.currentThread().getName()); number--; if (number < MAX - 5) { //包子空缺超过5个,通知做包子的赶紧做 this.notifyAll(); } } } } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); //5个做包子的 for (int i = 0; i < 5; i++) { new Thread(() -> { try { synchronizedDemo.produce(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } //20个买包子的 for (int i = 0; i < 20; i++) { new Thread(() -> { try { synchronizedDemo.consume(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }
produce()和consume()方法中在调用 this.wait() 后,之前手快写了个return。。。
排查了半天,重走了下逻辑才发现。
排查过程中,理解了下 return 和不启用 notifyAll() 的线程统计。
1. return + 启用notifyAll()
此时对应线程就结束了,会看到有几个线程(4-5个)处于WAITING状态。
2. continue + 不启用 notifyAll()
所有线程最终都会进入WAITING状态。
二、Condition
public class ConditionDemo { //类似包子铺场景:包子最多提前做好10个,少于10个就再做;卖完了,买包子的就得等着 //Condition版本 private final int MAX = 10; private int number = 0; Lock lock = new ReentrantLock(); Condition full = lock.newCondition();//满状态条件 Condition empty = lock.newCondition();//空状态条件 public void produce() throws InterruptedException { lock.lock(); if (number == MAX) { full.await(); return; } //生产者再生产 System.out.println("+++++第 " + ++number + " 个包子被做出来了!" + Thread.currentThread().getName()); if (number >= 5) { //生产出至少5个包子,通知赶紧买包子 empty.signalAll(); } lock.unlock(); } public void consume() throws InterruptedException { lock.lock(); if (number == 0) { empty.await(); return; } //消费者再消费 System.out.println("-----第 " + number-- + " 个包子被买了!" + Thread.currentThread().getName()); if (number <= MAX - 5) { //剩余包子不足,赶紧生产 full.signalAll(); } lock.unlock(); } public static void main(String[] args) { ConditionDemo conditionDemo = new ConditionDemo(); //5个做包子的 for (int i = 0; i < 5; i++) { new Thread(() -> { while (true) { try { conditionDemo.produce(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } //20个买包子的 for (int i = 0; i < 20; i++) { new Thread(() -> { while (true) { try { conditionDemo.consume(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } }
清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己
-- 共勉