ReentrantLock条件变量使多个线程顺序执行

 更新时间:2022年12月19日 10:13:52   作者:一一哥Sun  
这篇文章主要为大家介绍了ReentrantLock条件变量使多个线程顺序执行,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一. 前言

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

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

二. 解决方案

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

通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行;

通过倒数计时器CountDownLatch实现;

通过创建单一化线程池 newSingleThreadExecutor()实现;

通过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 让多个线程有序执行.

以上就是ReentrantLock条件变量使多个线程顺序执行的详细内容,更多关于ReentrantLock多个线程顺序执行的资料请关注脚本之家其它相关文章!

相关文章

  • Mybatis-Plus根据自定义注解实现自动加解密的示例代码

    Mybatis-Plus根据自定义注解实现自动加解密的示例代码

    我们把数据存到数据库的时候,有些敏感字段是需要加密的,从数据库查出来再进行解密,如果我们使用的是Mybatis框架,那就跟着一起探索下如何使用框架的拦截器功能实现自动加解密吧,需要的朋友可以参考下
    2024-06-06
  • SpringBoot 项目打成 jar后加载外部配置文件的操作方法

    SpringBoot 项目打成 jar后加载外部配置文件的操作方法

    这篇文章主要介绍了SpringBoot 项目打成 jar后加载外部配置文件的操作方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Java 日期转换详解及实例代码

    Java 日期转换详解及实例代码

    这篇文章主要介绍了Java 日期转换详解及实例代码的相关资料,需要的朋友可以参考下
    2016-11-11
  • 浅析Jmeter多用户token使用问题

    浅析Jmeter多用户token使用问题

    这篇文章主要介绍了Jmeter多用户token使用问题,通过具体的例子给大家介绍了Jmeter多用户token使用场景接口分析,需要的朋友可以参考下
    2021-10-10
  • jar包运行时提示jar中没有主清单属性的解决

    jar包运行时提示jar中没有主清单属性的解决

    这篇文章主要介绍了jar包运行时提示jar中没有主清单属性的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java中BigDecimal类与int、Integer使用总结

    Java中BigDecimal类与int、Integer使用总结

    这篇文章主要给大家介绍了关于Java中BigDecimal类与int、Integer使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • mybatisplus实现自动创建/更新时间的项目实践

    mybatisplus实现自动创建/更新时间的项目实践

    Mybatis-Plus提供了自动填充功能,可以通过实现MetaObjectHandler接口来实现自动更新时间的功能,本文就来介绍一下mybatisplus实现自动创建/更新时间的项目实践,感兴趣的可以了解下
    2024-01-01
  • 面试中遇到的java逃逸分析问题

    面试中遇到的java逃逸分析问题

    这篇文章主要介绍了面试中遇到的java逃逸分析问题,逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。,需要的朋友可以参考下
    2019-06-06
  • java模拟ajax访问另一个项目的controller代码实例

    java模拟ajax访问另一个项目的controller代码实例

    今天小编就为大家分享一篇关于java模拟ajax访问另一个项目的controller代码实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • java9中gc log参数迁移

    java9中gc log参数迁移

    本篇文章给大家详细讲述了java9中gc log参数迁移的相关知识点,对此有需要的朋友可以参考学习下。
    2018-03-03

最新评论