多线程之间是如何通信的
创始人
2024-06-02 22:39:14
0

一.多线程之间通信场景

1.有两个线程,线程1和线程2;

2.线程1向一个集合里面依次添加元素"abc"字符串,一共添加十次,当添加到第五次的时候,希望线程2能够收到线程1的通知,然后线程2执行相关的业务操作。

二.实现方式

线程之间的通信有一般有两种方式:共享内存消息传递。以下是基于这两种方式的解决方案

1.使用volatile关键字

基于volatile关键字来实现线程间相互通信是使用共享内存的思想。
共享内存 大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。

具体代码实现如下

package com.tangbb.test1;import java.util.ArrayList;
import java.util.List;/*** @DESCRIPTION:* @USER: tangbingbing* @DATE: 2023/3/13 9:49*/
public class test1 {// 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知static volatile boolean notice = false;public static void main(String[] args) {List list = new ArrayList<>();// 实现线程AThread threadA = new Thread(() -> {for (int i = 1; i <= 10; i++) {list.add("abc");System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}if (list.size() == 5)notice = true;}});// 实现线程BThread threadB = new Thread(() -> {while (true) {if (notice) {System.out.println("线程B收到通知,开始执行自己的业务...");break;}}});// 需要先启动线程BthreadB.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 再启动线程AthreadA.start();}
}

2.使用Object类的wait() 和 notify() 方法

wait()作用是使当前执行该代码的线程进入该对象锁的阻塞队列中进行等待(立即释放锁,进入等待锁的阻塞队列,下次被唤醒时,会接着往下执行) 配合notify()、notifyaAll()使用

package com.tangbb.test1;import java.util.ArrayList;
import java.util.List;/*** @DESCRIPTION:* @USER: tangbingbing* @DATE: 2023/3/13 9:49*/
public class test1 {public static void main(String[] args) {// 定义一个锁对象Object lock = new Object();List  list = new ArrayList<>();// 实现线程AThread threadA = new Thread(() -> {synchronized (lock) {for (int i = 1; i <= 10; i++) {list.add("abc");System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}if (list.size() == 5)lock.notify();// 唤醒B线程}}});// 实现线程BThread threadB = new Thread(() -> {while (true) {synchronized (lock) {if (list.size() != 5) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程B收到通知,开始执行自己的业务...");break;}}});// 需要先启动线程BthreadB.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 再启动线程AthreadA.start();}}

 在线程A发出notify()唤醒通知之后,依然是走完了自己线程的业务之后,线程B才开始执行

正好说明了,在执行 notify 方法后,当前线程不会马上释放该对象锁,被通知的线程也并不能马上获取该对象锁,要等到执行 notify() 方法的线程将程序执行完,也就是退出 synchronized 代码块后,当前线程才会释放锁,被通知线程才可以获取该对象锁。

3.使用JUC工具类 CountDownLatch

CountDownLatch基于AQS框架,相当于也是维护了一个线程间共享变量state

package com.tangbb.test1;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;/*** @DESCRIPTION:* @USER: tangbingbing* @DATE: 2023/3/13 9:49*/
public class test1 {public static void main(String[] args) {CountDownLatch countDownLatch = new CountDownLatch(1);List  list = new ArrayList<>();// 实现线程AThread threadA = new Thread(() -> {for (int i = 1; i <= 10; i++) {list.add("abc");System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}if (list.size() == 5)countDownLatch.countDown();}});// 实现线程BThread threadB = new Thread(() -> {while (true) {if (list.size() != 5) {try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程B收到通知,开始执行自己的业务...");break;}});// 需要先启动线程BthreadB.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 再启动线程AthreadA.start();}
}

4.基本LockSupport实现

LockSupport 是一种非常灵活的实现线程间阻塞和唤醒的工具,使用它不用关注是等待线程先进行还是唤醒线程先运行,但是得知道线程的名字。

package com.tangbb.test1;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.LockSupport;/*** @DESCRIPTION:* @USER: tangbingbing* @DATE: 2023/3/13 9:49*/
public class test1 {public static void main(String[] args) {List list = new ArrayList<>();// 实现线程Bfinal Thread threadB = new Thread(() -> {if (list.size() != 5) {LockSupport.park();}System.out.println("线程B收到通知,开始执行自己的业务...");});// 实现线程AThread threadA = new Thread(() -> {for (int i = 1; i <= 10; i++) {list.add("abc");System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}if (list.size() == 5)LockSupport.unpark(threadB);}});threadA.start();threadB.start();}
}

相关内容

热门资讯

安卓系统home键隐藏,提升手... 你有没有发现,手机里的安卓系统越来越智能了?有时候,一些小小的改动就能带来大大的惊喜。今天,就让我来...
手机怎么刷屏安卓版系统,安卓手... 你有没有发现,现在手机刷屏简直成了朋友圈的标配?不管是美食、旅行还是日常琐事,大家都喜欢用手机刷屏来...
小米安卓系统电视机,畅享视听盛... 亲爱的读者们,你是否曾想过,家里的电视也能像智能手机一样智能呢?今天,就让我带你一起探索一下小米安卓...
安卓系统怎么设置最好的,nn`... 你有没有发现,安卓系统就像一个万能的魔法盒,里面藏着无数的小秘密和神奇的功能?想要让你的安卓手机发挥...
安卓哪个品牌系统顺畅,哪个品牌... 手机系统,这个话题可是让不少安卓用户头疼不已。市面上那么多品牌,哪个的系统用起来最顺畅呢?今天,就让...
安卓系统相机不能启动,安卓相机... 手机里的安卓系统相机突然不能启动了,这可真是让人头疼啊!你有没有遇到过这种情况呢?别急,今天就来跟你...
安卓原生系统时间校准,基于安卓... 手机时间不准了?别急,我来教你如何轻松搞定安卓原生系统时间校准! 话题引入:手机时间不准,是不是让你...
主机系统内存和安卓联机,主机系... 你有没有想过,为什么你的手机在玩大型游戏时总是卡得要命?又或者,为什么你的电脑在处理复杂任务时,反应...
安卓如何手机上刷系统,轻松升级... 你有没有想过,你的安卓手机是不是已经有点儿“老态龙钟”了呢?别急,别急,今天就来教你怎么给它来个“青...
苹果系统观战安卓好友,观战新体... 亲爱的读者,你是否也有过这样的经历:一边享受着苹果系统的优雅与流畅,一边又忍不住好奇地观战安卓好友们...
安卓系统最好是哪个,最佳生成方... 你有没有想过,手机里的安卓系统哪个才是最适合你的呢?在这个信息爆炸的时代,手机已经成为了我们生活中不...
改时间安卓系统vivo,探索v... 你有没有发现,最近你的vivo手机有点儿“慢吞吞”的?别急,别急,让我来给你支个招儿,让你的安卓系统...
安卓系统的旋钮在哪,旋钮生成位... 你有没有发现,有时候手机上的小细节也能让人头疼不已?比如说,安卓系统的旋钮在哪?这问题看似简单,但不...
安卓手机app系统软件,探索安... 你有没有发现,现在手机里的app简直就像是个小宇宙,各种功能应有尽有,让人眼花缭乱。尤其是安卓手机,...
win111安卓子系统,开启跨... 哇,你有没有听说最近的大新闻?那就是Windows 11的安卓子系统!是的,你没听错,Windows...
游戏摇杆连安卓系统电视,畅享游... 你有没有想过,家里的安卓系统电视也能玩起游戏来?没错,就是那种让你手舞足蹈、热血沸腾的游戏摇杆!今天...
nokia平板系统兼容安卓,尽... 你有没有想过,那些曾经陪伴我们度过无数时光的诺基亚手机,现在竟然也能摇身一变,成为平板电脑的得力助手...
安卓原生系统是什么品牌,探索安... 你有没有想过,为什么你的手机那么流畅,界面那么美观?这背后,可是有一个强大的“大脑”在默默支撑着呢!...
安卓3大操作系统,从三大分支看... 你知道吗?在安卓的世界里,操作系统可是有着三大巨头呢!它们就像安卓世界的三驾马车,各自有着独特的魅力...
开源文件管理系统安卓,打造个性... 你有没有想过,手机里那些乱糟糟的文件,要是能有个好帮手,生活该有多轻松啊?今天,就让我带你走进一个神...