JUC并发编程学习笔记(三)生产者和消费者问题
1.JUC并发编程学习笔记(二)Lock锁(重点)2.JUC并发编程学习笔记(一)认知进程和线程
3.JUC并发编程学习笔记(三)生产者和消费者问题
4.JUC并发编程学习笔记(四)8锁现象5.JUC并发编程学习(五)集合类不安全6.JUC并发编程学习笔记(六)Callable(简单)7.JUC并发编程学习笔记(七)常用的辅助类8.JUC并发编程学习笔记(八)读写锁9.JUC并发编程学习笔记(九)阻塞队列10.JUC并发编程学习笔记(十)线程池(重点)11.JUC并发编程学习(十一)四大函数式接口(必备)12.JUC并发编程学习笔记(十二)Stream流式计算13.JUC并发编程学习(十三)ForkJoin14.JUC并发编程学习笔记(十四)异步回调15.JUC并发编程学习笔记(十五)JMM16.JUC并发编程学习笔记(十七)彻底玩转单例模式17.JUC并发编程学习笔记(十九)原子引用18.JUC并发编程(终章)各种锁的理解19.JUC并发编程学习笔记(十六)Volatile20.JUC并发编程学习笔记(十八)深入理解CAS生产者和消费者问题
synchronized版-> wait/notify
juc版->Lock
面试:单例模式、排序算法、生产者和消费者、死锁
生产者和消费者问题 Synchronized版
package org.example.pc; public class A { public static void main(String[] args) { Date date = new Date(); new Thread(()->{ for (int i = 0; i < 20; i++) { date.increment(); } },"A").start(); new Thread(()->{ for (int i = 0; i < 20; i++) { date.decrement(); } },"B").start(); } } //判断等待、业务、通知 class Date{ private int number = 0; public synchronized void increment(){ if (number!=0){ try { //不等于0就让该线程等待 this.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } number++; // 打印加完后的值 System.out.println(Thread.currentThread().getName()+"=>"+number); // 通知其他线程,我完成了 this.notify(); } public synchronized void decrement(){ if (number!=1){ try { this.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); this.notify(); } }
存在的问题:A、B、C、D四个线程
在线程中判断业务完成唤醒等待应该使用while循环判断,而非if判断,因为if判断值判断一次,在线程中存在一种状态叫虚假唤醒。
JUC版生产者和消费者问题
代码实现
package org.example.pc; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; //判断等待、业务、通知 public class Date { private int number = 0; private Lock lock = new ReentrantLock(); private Condition inCondition = lock.newCondition(); public void increment() { try { lock.lock(); while (number != 0) { inCondition.await(); } number++; // 打印加完后的值 System.out.println(Thread.currentThread().getName() + "=>" + number); // 通知其他线程,我完成了 inCondition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void decrement() { try { lock.lock(); while (number != 1) { inCondition.await(); } number--; System.out.println(Thread.currentThread().getName() + "=>" + number); inCondition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
Condition 精准的通知唤醒线程
在传统并发编程中,通过notifily唤醒线程后所有线程都是随机获取到资源的,JUC中可以通过Condition来精准的控制要唤醒哪一个线程资源。任何一个新技术的出现都不会只是为了实现之前已有的效果
代码实现
package org.example.pc; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class C { public static void main(String[] args) { DateC dateC = new DateC(); new Thread(()->{ for (int i = 0; i < 10; i++) dateC.plantA(); },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) dateC.plantB(); },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) dateC.plantC(); },"C").start(); } } class DateC { private int number = 1; private Lock lock = new ReentrantLock(); private Condition inCondition1 = lock.newCondition(); private Condition inCondition2 = lock.newCondition(); private Condition inCondition3 = lock.newCondition(); public void plantA(){ try { lock.lock(); while (number!=1){ inCondition1.await(); } System.out.println(Thread.currentThread().getName()); number=2; inCondition2.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void plantB(){ try { lock.lock(); while (number!=2){ inCondition2.await(); } System.out.println(Thread.currentThread().getName()); number=3; inCondition3.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void plantC(){ try { lock.lock(); while (number!=3){ inCondition3.await(); } System.out.println(Thread.currentThread().getName()); number=1; inCondition1.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构