java多线程 线程交替执行(同步)的各种实现方案

目录

  • java多线程 线程交替执行(同步)的各种实现方案
    • 需求
  • 指定具体执行顺序
    • 实现一:wait_notify机制 + Thread标志位
    • 实现二:lock_condition机制 + Thread标志位
    • 实现三:semaphore信号量
  • 不指定具体执行顺序,只交替执行
    • 实现一:synchronized和wait、notify实现
    • 实现二:lock和condition实现
  • 总结

java多线程 线程交替执行(同步)的各种实现方案

需求

有两个线程,A线程内容是输出数字1到26,B线程内容是输出字母a-z,

要求A B 线程交替执行,最终输出如下图所示

在这里插入图片描述

指定具体执行顺序

要求A B 线程交替执行,并且必须是A线程先执行,B后执行

解决思路:初始指定一个标志位,标记哪个线程可以运行,只要当前标志位不是当前线程(不满足运行条件),就一直等待

伪代码

线程A{while(满足当前线程的运行条件)不满足,则直接释放锁并进入wait状态执行当前线程内容通知下一个执行的线程,让其运行条件为true
}

实现一:wait_notify机制 + Thread标志位

实现思路:

  • 用标志位Thread标识哪个先执行
  • 线程A:只要标志位不是A就不满足运行条件,就等待;否则才执行内容,并切换Thread为下一个要执行的线程B
  • 线程A:只要标志位不是B就不满足运行条件,就等待;否则才执行内容,并切换Thread为下一个要执行的线程A

拓展:如果是三个线程交替,只需要让B线程执行完后把threadName标记为C,然后让C线程执行完后把threadName标记为A即可

public class AlternateThreads {private static final Object lock = new Object();private static String threadName = "A";public static void main(String[] args) {Thread threadA = new Thread(() -> {synchronized (lock) {for (int i = 1; i <= 26; i++) {//threadName只要不是线程A,就等待while (threadName!="A") {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(i + " ");threadName = "B";lock.notify();}}});Thread threadB = new Thread(() -> {synchronized (lock) {for (char c = 'a'; c <= 'z'; c++) {//threadName只要不是线程A,就等待while (threadName!="B") {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(c + " ");threadName = "A";lock.notify();}}});threadA.start();threadB.start();}
}

实现二:lock_condition机制 + Thread标志位

实现思路:和wait_notiy实现的基本一致,也是,只不过wait变成了await,notify变成了signal

拓展:如果是三个线程交替,只需要让B线程执行完后把threadName标记为C,然后让C线程执行完后把threadName标记为A即可

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class AlternateThreads {private static Lock lock = new ReentrantLock();private static Condition condition = lock.newCondition();private static String threadName = "A";/**目标:交替执行的基础上,必须先执行A,再执行B* 方案:lock_condition机制 + Thread标志位* 实现思路:和我wait_notiy实现的基本一致,也是,只不过wait变成了await,notify变成了signal* @param args*/public static void main(String[] args) {Thread threadA = new Thread(() -> {try {lock.lock();for (int i = 1; i <= 26; i++) {while (threadName!="A") {condition.await();}System.out.print(i + " ");threadName = "B";condition.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}});Thread threadB = new Thread(() -> {try {lock.lock();for (char c = 'a'; c <= 'z'; c++) {while (threadName!="B") {condition.await();}System.out.print(c + " ");threadName = "A";condition.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}});threadA.start();threadB.start();}
}

实现三:semaphore信号量

实现思路:

  • 线程A:开始执行时,先申请信号量s1,执行结束后,再释放信号量s2,让B结束等待;
  • 线程B:开始执行时,先申请信号量s2,执行结束后,再释放信号量s1,让A结束等待;
  • 初始化:设置线程A对应的信号量初始为1,B线程对应信号量为0,保证A先执行

拓展:如果是三个线程交替,只需要让B线程执行完后release信号量C,然后让C线程执行完后release信号量A

public class AlternateThreads {private static Semaphore semaphoreA = new Semaphore(1);private static Semaphore semaphoreB = new Semaphore(0);public static void main(String[] args) {Thread threadA = new Thread(() -> {for (int i = 1; i <= 26; i++) {try {semaphoreA.acquire();//申请信号量ASystem.out.print(i + " ");semaphoreB.release();//通知B可以运行了} catch (InterruptedException e) {e.printStackTrace();}}});Thread threadB = new Thread(() -> {for (char c = 'a'; c <= 'z'; c++) {try {semaphoreB.acquire();//申请信号量BSystem.out.print(c + " ");semaphoreA.release();//通知A可以运行了} catch (InterruptedException e) {e.printStackTrace();}}});threadA.start();threadB.start();}
}

不指定具体执行顺序,只交替执行

要求:如果不要求A和B哪个先执行,只要求A和B交替执行

解决思路:保证互斥,直接执行内容,再notify唤醒其它线程,最后自己再释放锁进入wait状态

伪代码

线程A{while(是否满足当前线程A的运行条件?)不满足,则直接释放锁并进入wait执行当前线程内容通知下一个执行的线程B,让其运行条件为true
}

为什么这样不能保证哪个先执行?

因为各个线程只要竞争到锁,就会直接运行,后续再wait,而不是先判断是否要wait

实现一:synchronized和wait、notify实现

public class ThreadSyn {//实现方式一,synchronized和wait、notify实现,不保证先执行哪一个public static void test1() {Object lock = new Object();boolean flag = false;Thread a = new Thread(() -> {synchronized (lock) {for (int i = 1; i <= 26; i++) {//直接运行System.out.print(i + " ");try {//先唤醒,再阻塞lock.notify();lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}lock.notify();//结束后唤醒,防止死锁}});Thread b = new Thread(() -> {synchronized (lock) {for (char ch = 'a'; ch <= 'z'; ch++) {//直接运行System.out.print(ch + " ");try {//先唤醒,再阻塞lock.notify();lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}lock.notify();//结束后唤醒,防止死锁}});a.start();b.start();}

实现二:lock和condition实现

    //实现方式二:lock和condition实现,A B交替执行,也不确定先执行的是哪个,只能确保轮流执行public static void test2() {Lock lock = new ReentrantLock();Condition condition_A = lock.newCondition();Condition condition_B = lock.newCondition();Thread a = new Thread(() -> {lock.lock();for (int i = 1; i <= 26; i++) {//直接运行System.out.print(i + " ");try {//先唤醒,再阻塞condition_B.signal();//唤醒线程Bcondition_A.await();//等待条件A} catch (InterruptedException e) {e.printStackTrace();}}condition_B.signal();//执行完for循环后需释放最后在等待的B线程,防止死锁lock.unlock();});Thread b = new Thread(() -> {lock.lock();for (char ch = 'a'; ch <= 'z'; ch++) {System.out.print(ch + " ");//执行线程操作try {condition_A.signal();//唤醒线程Acondition_B.await();//等待条件B} catch (InterruptedException e) {e.printStackTrace();}}condition_A.signal();//执行完for循环后需释放最后在等待的A线程,防止死锁lock.unlock();});a.start();b.start();}

总结

如果想要指定执行顺序,则需要用信号量,或者自己实现一个标志位去模拟信号量

如果不需要指定执行顺序,则谁先竞争到锁就谁先执行,执行完后唤醒另一个线程,再进入wait状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/697715.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

极验3滑块逆向分析

1、底图还原 下 断点&#xff0c;可以分析底图还原逻辑 2、跟W值 var Str_Unicodefunction(str){var unid\\u00;for(let i0,lenstr.length;i<len;i){if(i<len-1){unidstr.charCodeAt(i).toString(16)\\u00;}else if(ilen-1){unidstr.charCodeAt(i).toString(16);}}re…

Java | Leetcode Java题解之第88题合并两个有序数组

题目&#xff1a; 题解&#xff1a; class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int p1 m - 1, p2 n - 1;int tail m n - 1;int cur;while (p1 > 0 || p2 > 0) {if (p1 -1) {cur nums2[p2--];} else if (p2 -1) {cur nums1[p…

ubuntu 22.04 安装 RTX 4090 显卡驱动 GPU Driver(PyTorch准备)

文章目录 1. 参考文章2. 检查GPU是Nvidia3. 卸载已有驱动3.1. 命令删除3.2. 老驱动包 4. 官网下载驱动5. 运行5.1. 远程安装关闭交互界面5.2. 运行5.3. 打开交互界面 6. 检测与后续安装 1. 参考文章 https://blog.csdn.net/JineD/article/details/129432308 2. 检查GPU是Nvid…

Golang | Leetcode Golang题解之第88题合并两个有序数组

题目&#xff1a; 题解&#xff1a; func merge(nums1 []int, m int, nums2 []int, n int) {for p1, p2, tail : m-1, n-1, mn-1; p1 > 0 || p2 > 0; tail-- {var cur intif p1 -1 {cur nums2[p2]p2--} else if p2 -1 {cur nums1[p1]p1--} else if nums1[p1] > n…

基于NTP服务器获取网络时间的实现

文章目录 1 NTP1.1 简介1.2 包结构1.3 UNIX 时间戳和NTP时间戳 2 代码实现2.1 实现步骤2.2 完整代码 3 结果 在某些场景下&#xff0c;单片机需要通过网络获取准确的时间进行数据同步&#xff0c;例如日志记录、定时任务等。然而&#xff0c;单片机本身无法直接获得准确的标准时…

(八)SQL基础知识练习题(选择题)(下)#CDA学习打卡

本文整理了SQL基础知识相关的练习题&#xff0c;共133道&#xff0c;可作为CDA一级的补充习题&#xff0c;也适用于刚入门初级SQL想巩固基础的同学。来源&#xff1a;如荷学数据科学题库&#xff08;技术专项-SQL&#xff09;。暂时按照原题库顺序present&#xff0c;如有需要之…

vue+springboot用户注销功能

vue文件前端 <el-button type"warning" plain click"handleDeletion">注 销</el-button> // 注销 const handleDeletion (userName) > {ElMessageBox.confirm(注销该用户所有信息后无法恢复&#xff0c;您确认注销吗?, 注销确认, { type…

啥都吃的打字练习软件TL(TypeLetters)

今天给大家安利一款啥都吃的打字练习软件——TL&#xff08;TypeLetters&#xff09;。 为什么说TL啥都吃呢&#xff1f;很简单&#xff0c;因为不管是科技的、还是时事的、或者潮流的、或者热点的&#xff0c;凡是英文的资料TL都能通通吃下去&#xff0c;所以说TL是来者不拒&…

24年湖南三支一扶报名详细流程(电脑报名)

24年湖南三支一扶报名详细流程&#xff08;电脑报名&#xff09; #湖南三支一扶 #湖南三支一扶考试 #三支一扶报名照片 #三支一扶考试 #三支一扶 #湖南省三支一扶

新的语言学习系统: 记忆镶嵌

摘要 记忆镶嵌是由多个关联记忆网络协同工作来完成感兴趣的预测任务。与transformer类似,记忆镶嵌具有组合能力和上下文学习能力。与transformer不同,记忆镶嵌以相对透明的方式实现这些能力。该研究在玩具示例上展示了这些能力,并且还表明记忆镶嵌在中等规模语言建模任务上的表…

Python | Leetcode Python题解之第88题合并两个有序数组

题目&#xff1a; 题解&#xff1a; class Solution:def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:"""Do not return anything, modify nums1 in-place instead."""p1, p2 m - 1, n - 1tail m n - 1whi…

跟TED演讲学英文:How the US is destroying young people‘s future by Scott Galloway

How the US is destroying young people’s future Link: https://www.ted.com/talks/scott_galloway_how_the_us_is_destroying_young_people_s_future? Speaker: Scott Galloway Date: April 2024 文章目录 How the US is destroying young peoples futureIntroductionVoc…