当前位置: 首页 > web >正文

线程间通信


线程间通信的模型有两种:共享内存 和 消息传递,以下方式都是基本这两种模型来实现的。

场景—两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1。要求用线程间通信

3.1 synchronized方案


使用 wait(); notify();

public class TestMain { /** ● 交替加减*/ public static void main(String[] args){ DemoClass demoClass = new DemoClass();         new Thread(() ->{             for (int i = 0; i < 5; i++) { demoClass.increment(); } }, "线程 A").start(); new Thread(() ->{             for (int i = 0; i < 5; i++) {                 demoClass.decrement(); } }, "线程 B").start(); } 
} 
class DemoClass{     //加减对象 private int number = 0; /** * 加 1 */ public synchronized void increment() { try { while (number != 0){ this.wait(); } number++; System.out.println(currentThread().getName() + "加一成功,值为:" + number); //唤醒其他的线程notifyAll(); }catch (Exception e){ e.printStackTrace(); } } /** * 减一 */ public synchronized void decrement(){ try { while (number != 1){ this.wait(); } number--; System.out.println(currentThread().getName() + "减一成功,值为:" + number); notifyAll(); }catch (Exception e){ e.printStackTrace(); } } 
} 

3.2 Lock 方案


使用 Condition condition.await(); condition.signal();

import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; class DemoClass{     // 加减对象 private int number = 0; // 声明锁     private Lock lock = new ReentrantLock(); // 声明钥匙 private Condition condition = lock.newCondition(); /** * 加 1 */ public void increment() { try {             lock.lock(); // 加锁        while (number != 0){                 condition.await();  //等待} number++; System.out.println(currentThread().getName() + "加一成功,值为:" + number);//	通知其他等待的线程condition.signalAll(); }catch (Exception e){ e.printStackTrace();         }finally {             lock.unlock(); //释放锁} } /** * 减一 */ public void decrement(){ try {             lock.lock();             while (number != 1){                 condition.await(); } number--; System.out.println(currentThread().getName() + "减一成功,值为:" + number); condition.signalAll(); }catch (Exception e){ e.printStackTrace();         }finally {             lock.unlock();                                                   } } 
} 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; class DemoClass{ //通信对象:0--打印 A  1---打印 B  2----打印 C private int number = 0; //声明锁     private Lock lock = new ReentrantLock(); //声明钥匙 A private Condition conditionA = lock.newCondition(); //声明钥匙 B private Condition conditionB = lock.newCondition(); //声明钥匙 C private Condition conditionC = lock.newCondition(); 
}

3.4 线程间定制化通信


3.4.1 案例介绍

问题: A 线程打印 5 次 A,B 线程打印 10 次 B,C 线程打印 15 次 C 。

按照此顺序循环 10 轮

3.4.2 实现流程

代码如下:

//	标志位 AA 1   BB 2  CC 3
private int number = 1; Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition(); 
private Condition conditionB = lock.newCondition(); 
private Condition conditionC = lock.newCondition(); //	5 次
public void printA(int j){ try {             lock.lock();             while (number != 1){conditionA.await(); } System.out.println(currentThread().getName() + "输出 A,第" + j + " 轮开始"); // 输出 5 次 A for (int i = 0; i < 5; i++) { System.out.println("A"); } // 修改标志位           number = 2;             //唤醒 BconditionB.signal(); } catch (Exception e){ e.printStackTrace();         } finally {lock.unlock(); } 
} //	10 次
public void printB(int j){ try {             lock.lock();while (number != 2){conditionB.await(); } System.out.println(currentThread().getName() + "输出 B,第" + j + " 轮开始"); //输出 10 次 B for (int i = 0; i < 10; i++) { System.out.println("B"); } // 修改标志位number = 3;//唤醒 CconditionC.signal(); } catch (Exception e){ e.printStackTrace();         }finally {lock.unlock(); }
}//	15 次
public void printC(int j){ try {             lock.lock();while (number != 3){conditionC.await(); } System.out.println(currentThread().getName() + "输出 C,第" + j + " 轮开始"); //输出 15 次 C for (int i = 0; i < 15; i++) { System.out.println("C"); } System.out.println("-----------------------------------------"); //	修改标志位number = 1;//唤醒 AconditionA.signal(); } catch (Exception e){ e.printStackTrace(); } finally {lock.unlock(); } 
} 

测试类

/** 
● 关键字实现线程交替加减 
*/ 
public class TestVolatile { /** ● 交替加减 ● @param args */ public static void main(String[] args){ DemoClass demoClass = new DemoClass(); new Thread(() ->{             for (int i = 1; i <= 10; i++) {                 demoClass.printA(i); } }, "A 线程").start(); new Thread(() ->{for (int i = 1; i <= 10; i++) { demoClass.printB(i); } }, "B 线程").start(); new Thread(() ->{for (int i = 1; i <= 10; i++) {demoClass.printC(i); } }, "C 线程").start(); } 
} 

http://www.xdnf.cn/news/20580.html

相关文章:

  • 使用Terraform管理阿里云基础设施
  • 319章:使用Scrapy框架构建分布式爬虫
  • 还在重启应用改 Topic?Spring Boot 动态 Kafka 消费的“终极形态”
  • 企业级 Django 日志配置示例
  • 【三维生成】Matrix-3D:全向可探索的三维世界生成
  • 基于脚手架微服务的视频点播系统-播放控制部分
  • 算法题(201):传球游戏
  • 低代码开发平台.技术
  • Github操作
  • 训练+评估流程
  • java设计模式二、工厂
  • 5-2EFCore性能优化
  • FLINK:水位线的介绍
  • C/C++数据结构之栈基础
  • FastAPI + LangChain 和 Spring AI + LangChain4j
  • qt creator新手入门以及结合sql server数据库开发
  • Spring Cloud Gateway 进行集群化部署
  • Vscode中开发VUE项目的调试方案
  • Android开发-Activity传递信息
  • [论文阅读] 人工智能 + 软件工程 | 首个仓库级多任务调试数据集!RepoDebug揭秘LLM真实调试水平
  • Objective-C方法参数标签怎么设置
  • 华为基于IPD的产品质量计划模板
  • 苍穹外卖Day12 | Apache POI、导出Excel报表、HttpServletResponse、工作台
  • Tomcat 日志文件名的命名规范
  • 腾讯云语音接口实现会议系统
  • 《sklearn机器学习——管道和复合估算器》可视化复合估计器
  • AI 驱动数据分析:开源 SQLBot 项目探索,基于大模型和 RAG 实现精准问数与图表挖掘
  • 小白AIGC短视频生成的第一课之混元AI视频
  • HTTPS优化简单总结
  • Unity UI 中最干净的点击区域实现:RaycastZone 完整实战讲解