第3章 线程间通信
线程间通信
对于两个线程a,b;
首先线程a:
(1) 判断:变量值如果为0
(2) 干活:变量值+1
(3) 通知:a线程通知b线程对变量-1
其次线程b:
(1) 判断:变量值如果为1
(2) 干活:变量值-1
(3) 通知:b线程通知a线程对变量+1
依次类推。。。
代码实现:方式一:synchronized关键字
package JUC.sync; //第一步 创建资源类,定义属性和操作方法 class Share { //初始值 private int number = 0; //+1的方法 public synchronized void incr() throws InterruptedException { //第二步 判断 干活 通知 if (number != 0) { //判断number值是否为0,如果不是0,等待 this.wait(); } //如果number值是0,就+1操作 number++; System.out.println(Thread.currentThread().getName()+" :: "+number); //通知其他线程 this.notifyAll(); } //-1的方法 public synchronized void decr() throws InterruptedException { //第二步 判断 干活 通知 if (number != 1) { //判断number值是否为1,如果不是1,等待 this.wait(); } //如果number值是1,就-1操作 number--; System.out.println(Thread.currentThread().getName()+" :: "+number); //通知其他线程 this.notifyAll(); } } public class ThreadDemo1 { //第三步 创建多个线程,调用资源类的操作方法 public static void main(String[] args) { Share share = new Share(); //创建线程 new Thread(()->{ for (int i = 0; i < 10; i++) { try { share.incr();//+1 } catch (InterruptedException e) { e.printStackTrace(); } } },"AA").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { share.decr();//-1 } catch (InterruptedException e) { e.printStackTrace(); } } },"BB").start(); } }
如果线程为4个,会出现 虚假唤醒 的问题
解决方案:
判断语句由 if 改为 while。while条件不管wait什么时候睡,什么时候醒,都要经过判断条件。
代码实现:方式二:Lock接口
package JUC.lock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; //第一步 创建资源类,定义属性和操作方法 class Share { private int number = 0; //创建Lock final Lock lock = new ReentrantLock(); final Condition condition = lock.newCondition(); //+1 public void incr() throws InterruptedException { //上锁 lock.lock(); try{ //判断 while(number != 0){ condition.await(); } //干活 number++; System.out.println(Thread.currentThread().getName()+" :: "+number); //通知 condition.signalAll(); } finally { //解锁 lock.unlock(); } } //-1 public void decr() throws InterruptedException { //上锁 lock.lock(); try{ //判断 while(number != 1){ condition.await(); } //干活 number--; System.out.println(Thread.currentThread().getName()+" :: "+number); //通知 condition.signalAll(); } finally { //解锁 lock.unlock(); } } } public class ThreadDemo2 { public static void main(String[] args) { Share share = new Share(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { share.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"AA").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { share.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"BB").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { share.incr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"CC").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { share.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } },"DD").start(); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器