使用ReentrantLock中的条件变量让多个线程顺序执行

news2025/1/16 5:54:57

一. 前言

近日壹哥的一个学生在参加某公司校招面试时,遇到一个多个线程顺序执行的面试题,特意记录下来和大家分享一下,这个题目的具体要求是这样的:

假设有3个线程 a,b,c,要求三个线程一起进入到就绪态,执行时一定按照 a-->b-->c的顺序执行。即使a或者b线程进入到了阻塞态,也一定按照a-->b-->c的顺序运行线程。请问该如何保证实现这个需求呢?

二. 解决方案

关于这道题,壹哥百度一下网上常见的实现思路,大致有4种解决方案:

  1. 通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行;
  2. 通过倒数计时器CountDownLatch实现;
  3. 通过创建单一化线程池 newSingleThreadExecutor()实现;
  4. 通过ReentrantLock 中的条件变量实现;

今天壹哥先使用ReentrantLock 的条件变量来实现这个题目中的需求。

三. 使用ReentrantLock 条件变量

首先咱们来了解一下,什么是ReentrantLock 条件变量(Condition)。

ReentrantLock 中的条件变量功能,类似于普通 synchronized 的 wait、notify,我们可以使用Reentrantlock 锁,配合 Condition 对象上的 await()和 signal()或 signalAll()方法,来实现线程间协作。与synchronized的wait和notify不同之处在于,ReentrantLock中的条件变量可以有多个,可以实现更精细的控制线程。

Condition中常用的方法API有如下这些:

ReentrantLock代码实现:

class ShareDataLock{
    // 线程执行的条件 1:线程1执行 2:线程2执行 3:线程3执行
    int number =1;
    // 锁
    Lock lock = new ReentrantLock();
    // 从锁中获得3个条件变量
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();

    // 第一个线程run之后执行的方法
    public void f1(){
        lock.lock();
        try {
            // 如果条件值不为1 就挂起等待
            while(number!=1){
                condition1.await();
            }
            // 故意阻塞100毫秒,看看其他的线程会不会不再排队
            Thread.sleep(100);
            System.out.println("------1--------");
            // 线程1 执行完毕 把变量设置为2
            number = 2;
            // 唤醒第2个条件变量
            condition2.signal();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
            // 不管抛没抛出异常都要解锁,防止线程死锁
          lock.unlock();
        }
    }
    
    public void f2(){
        lock.lock();
        try {
            while(number!=2){
                condition2.await();
            }
            System.out.println("------2--------");
            number = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public void f3(){
        lock.lock();
        try {
            while(number!=3){
                condition3.await();
            }
            System.out.println("------3--------");
            number = 1;
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


public class SynchronizedAndReentrantLockDemo {

    public static void main(String[] args) {
        ShareDataLock shareDataLock = new ShareDataLock();
        for (int i = 0; i < 10; i++) {
            // 3个线程分别执行1,2,3 3个方法 ,并且同时就绪
            new Thread(()->shareDataLock.f1(),"AA").start();
            new Thread(()->shareDataLock.f2(),"bb").start();
            new Thread(()->shareDataLock.f3(),"cc").start();
        }

    }
}

代码执行效果如下图:

 现在我们就会发现,3个线程已经可以被随意控制了,你会了吗?

四. 后话

如上文所述,让多个线程按顺序执行,网上常见的解决方案有4种。但大家要注意的是,面试官出这个题有一个先决条件,“要让所有的线程同时就绪,所以我们就可以排除使用join方法和使用单一化线程池的方案了。那么要想实现这个面试题中的需求,比较靠谱的方法只剩下ReentrantLock 中的条件变量和使用倒数计时器CountDownLatch两种方案了。今天咱们暂时先介绍条件变量的方法,壹哥会在日后的文章中介绍怎样使用CountDownLatch让多个线程有序执行敬请各位粉丝儿们继续期待哦。关注Java架构栈,天天干货都不断哦。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】775. 全局倒置与局部倒置

题目描述 给你一个长度为 n 的整数数组 nums &#xff0c;表示由范围 [0, n - 1] 内所有整数组成的一个排列。 全局倒置 的数目等于满足下述条件不同下标对 (i, j) 的数目&#xff1a; 0 < i < j < n nums[i] > nums[j] 局部倒置 的数目等于满足下述条件的下标 i 的…

01-Linux

1 初识Linux 在前面的课程中&#xff0c;我们无论是开发、测试。部署、存储都在Windwos操作系统的环境中&#xff0c;从今天开始我们一起学习下Linux,Linux系统和Windows系统最大的区别就是图形化界面操作和用途上有所差异&#xff0c;除了这两点&#xff0c;两者有异曲同工之…

跑通官方的yolov7-tiny实验记录(yolov7-tiny可作为yolov5s的对比实验网络)

目录1. 一些可用的参考链接2. 开始训练yolov72.1 --weights2.2 --cfg2.3 --data2.4 --hyp2.5 --epochs2.6 --batch-size2.7 --workers2.8 --name1. 一些可用的参考链接 官方YOLOv7 项目地址&#xff1a;https://github.com/WongKinYiu/yolov7如果想设置早停机制&#xff0c;可…

2022年TI杯模拟电⼦系统设计专题邀请赛——李萨如图形演示装置

任务 设计并实现李萨如&#xff08;Lissajous&#xff09;图形演示装置&#xff0c;如图 1 所示。输入正弦信号作为 x 轴信号&#xff0c;其峰峰值 2V&#xff0c;频率 1.5kHz~2kHz&#xff1b;对输入的正弦信号进行幅度和频率变换后产生 y 轴信号&#xff1b;装置显示器上显示…

CentOS7 离线安装 Python

目录1.前言2.下载Python及依赖环境&#xff08;1&#xff09;下载Python源码&#xff08;2&#xff09;下载Python依赖文件&#xff08;3&#xff09;下载gcc环境文件&#xff08;备用&#xff09;3.上传至离线服务器&#xff08;1&#xff09;核对已下载离线文件&#xff08;2…

基于PSO粒子群优化的汽车刹车稳定性数据matlab仿真与分析

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 刹车类别A 温度1 测试1 测试2 ....... 测试n 温度3 测试1 测试2 ....... 测试n ....... ....... 温度N 测试1 …

Java语言的过滤数据流

过滤数据流 为了解决不同数据流之间速度、数据格式差异的问题&#xff0c;以便提高输入/输出操作的效率&#xff08;特别是当需要大量的输入、输出操作的程序时&#xff09;&#xff0c;因此&#xff0c;Java贴心的提供了过滤流。 在已存在的数据流的基础上&#xff0c;过滤数…

IntelliJ IDEA

特色功能 IDEA所提倡的是智能编码&#xff0c;是减少程序员的工作&#xff0c;IDEA的特色功能有以下22点[1] &#xff1a; ● 智能的选取 在很多时候我们要选取某个方法&#xff0c;或某个循环或想一步一步从一个变量到整个类慢慢扩充着选取&#xff0c;IDEA就提供这种基于…

数据治理:数据标准的6大建设步骤及实施分享

“车同轨、书同文”&#xff0c;数字化时代&#xff0c;数据标准化是企业进行数字化转型的根基。数据标准与企业数据管理的每个域都相关&#xff0c;是数据治理工作的最基础内容。 元数据管理中&#xff0c;需要从业务属性、技术属性、管理属性三个方面定义数据标准&#xff1b…

第54篇-某网易易盾滑块请求data参数分析【2022-11-16】

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、流程分析三、data参数1.d值2.p值3.ext值一、前言 在很久以前我们使用selenium+OpenCV模拟过一次易盾盾滑块…

学习大数据之后可以做什么?未来发展怎么样?

当下&#xff0c;有很多小伙伴看中了大数据开发的前景&#xff0c;从而选择了学习大数据的行列当中来&#xff0c;只能说&#xff0c;坚持你的选择没有错~ 当下来看&#xff0c;可以说大数据是一种宝贵的战略资源&#xff0c;其潜在价值和增长速度正在改变着人类的工作、生活和…

人人开源搭建后台管理系统 逆向工程生成CRUD代码

一、什么是人人开源 也就是说和若依类似&#xff0c;都是快速帮我们开发一些简单的逻辑代码的&#xff0c;可以帮我们自动生成代码。 二、具体操作 我们现在就以renren-fast作为后台管理系统框架&#xff0c;用renren-fast-vue作为前端系统框架进行开发项目 具体操作如下所示&a…

做好一个BI项目的关键是什么

做好一个BI项目的关键是什么&#xff1f;有人会说&#xff0c;那肯定是报表&#xff0c;报表是数据分析最直接的成果展示&#xff0c;好的报表能够帮助企业从各种纷杂的信息中及时地发现关键有效的信息&#xff0c;从而为决策提供支持。诚然&#xff0c;报表很重要&#xff0c;…

SPI通信协议

目录一、什么是SPI协议二、SPI物理层三、SPI协议层一、什么是SPI协议 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;通讯协议&#xff0c;是 Motorola 公司提出的一种同步串行接口技术&#xff0c;是一种高速、全双工、同步通信总线&a…

【PTA-训练day7】L2-019 悄悄关注 + L1-027 出租

L2-019 悄悄关注 - 哈希表 PTA | 程序设计类实验辅助教学平台 1、java - 喜闻乐见超时 import java.util.*;public class Main {public static void main(String[] args){Scanner scnew Scanner(System.in);int nsc.nextInt();String[] namesc.nextLine().split(" "…

Centos7.6 源码编译部署percona mysql 5.7.39-42

Centos7.6 源码编译部署percona mysql 5.7.39-42 参考链接&#xff1a; mysql5.7.35源码编译安装部署CentOS7 编译安装 Percona Server 5.7percona Server for MySQL 5.7源码安装 一、部署环境准备 更换阿里云yum源 cd /etc/yum.repos.d/ mkdir bak && mv *.repo ba…

[附源码]java毕业设计江苏策腾智能科技公司人事管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

第1关:节点监听机制

ZooKeeper的监听机制 节点监听机制用以保证集群之间的一致性&#xff0c;以及服务器可以及时通知客户端节点状态的变化。 一个节点可以被监控&#xff0c;包括路径中存储的数据修改&#xff0c;子节点路径改变&#xff0c;当该节点发生修改&#xff0c;服务器可以通知设置监控…

AVS3帧间预测

帧间预测是去除时域冗余的重要工具&#xff0c;随着AVS标准发展&#xff0c;越来越多的帧间预测工具被加入标准&#xff0c;主要可以分为三类&#xff1a;预测编码类型、运动信息编码工具、CU级和子块级运动补偿。 预测编码类型 预测编码类型是指帧间预测的不同预测方式&#…

年产5000吨芒果醋工厂设计

摘要 - 1 - 1 绪论 - 6 - 1.1 概述 - 6 - 1.1.1 芒果醋的价值 - 6 - 1.1.2 芒果醋的市场贸易需求 - 6 - 1.1.3 国内芒果醋行业发展现状 - 7 - 1.2 本课题研究的意义 - 7 - 1.3 本课题的研究内容 - 8 - 1.4 设计原则 - 8 - 2 厂址选择 - 8 - 2.1 厂址选择 - 8 - 2.2 气温 - 9 - …