如何保证三个线程按顺序执行?不会我教你

news2024/10/6 14:30:14

👨‍🎓作者:bug菌
✏️博客:CSDN、掘金、infoQ、51CTO等
🎉简介:CSDN|阿里云|华为云|51CTO等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金 | InfoQ | 51CTO等社区优质创作者,全网粉丝合计15w+  ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。

...

✍️温馨提醒:本文字数:1999字, 阅读完需:约 5 分钟

🏆本文收录于《Java进阶实战》,专门攻坚指数提升。

本专栏致力打造最硬核 Spring Boot 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。

小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章点亮👍吧,您的点赞三连(收藏⭐+关注👨‍🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻‍♀️,创作不停💕,加油☘️

1. 前言

        哈喽,小伙伴们,你们好呀,今天我们就不整那枯燥无味的知识点了,偶尔换换口味,我们来玩点高级的;由于很多小伙伴都在给我传递一种负面情绪,今年的工作很难找,我就在想是不是八股文没准备充足啊?于是我就在总结高频笔试题,借此想把整理到的笔试题进行集合式的讨论,不仅帮助大家理解,也能帮助自己加深理解,何乐而不为呢。

2. 环境说明

本地的开发环境:

  • 开发工具:IDEA 2021.3
  • JDK版本: JDK 1.8
  • Spring Boot版本:2.3.1 RELEASE
  • Maven版本:3.8.2

3. 题目描述

        现有T1,T2,T3三个线程,请问你如何保证T1,T2,T3三线程按顺序(T1->T2->T3)执行?比如T2 在 T1 执行完后执行,T3 在 T2 执行完后执行.

4. 题目分析

        当你看到这道题,你们的第一反应是什么?反正我首先想到的就是 thread.join()方法,因为既满足题意也是最容易实现的,hh。

        思路1:使用join。不是要保证线程顺序执行嘛,thread.Join()作用就是把指定的线程加入到当前线程中,可以把两个并行执行的线程合并为顺序执行的线程,通俗点讲就是比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会开始执行线程B,以此类推,不就满足了题目要求。

        思路2:使用CountDownLatch。CountDownLatch(闭锁)是一个很有用的工具类,利用它我们可以拦截一个或多个线程使其在某个条件达到后再执行,可设置条件过滤。为什么这题要用它,是因为其内部提供了一个计数器,另外它还提供了一个countDown方法来操作计数器的值,每调用一次countDown方法计数器都会减1,直到计数器的值减为0时就代表条件已达到,所有因调用await方法而阻塞的线程都会被唤醒;这就是CountDownLatch的内部机制,看起来很简单,无非就是阻塞一部分线程让其在达到某个条件之后再执行。

        思路3:使用单个线程池。newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,以此达到顺序执行三个线程的目的。

5. 代码演示

        如下我将上述提供的三种思路进行代码实例演示,希望能辅助大家理解,代码仅供参考,如有疑问,评论区记得踢我,三人行,必有我师焉。

5.1 思路1&代码 

思路1【使用join】代码示例:

public class Test1 {

    // T1、T2、T3三个线程顺序执行
    public static void main(String[] args) {
        Thread t1 = new Thread(new runThread(null));
        Thread t2 = new Thread(new runThread(t1));
        Thread t3 = new Thread(new runThread(t2));
        t1.start();
        t2.start();
       t3.start();
    }

    static class runThread implements Runnable {
        //上一个线程
        private Thread beforeThread;

        //构造赋值
        public runThread(Thread beforeThread) {
            this.beforeThread = beforeThread;
        }

        //线程执行。
        public void run() {
            //保证第一个线程执行。
            if (beforeThread != null) {
                try {
                    //执行join(),合并为顺序执行的线程。
                    beforeThread.join();
                    System.out.println("thread start:" + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("thread start:" + Thread.currentThread().getName());
            }
        }
    }
}

执行结果截图:

5.2 思路2&代码 

 思路2【使用CountDownLatch】代码示例:

public class Test2 {

    public static void main(String[] args) {

        CountDownLatch c1 = new CountDownLatch(0);//计数器为0
        CountDownLatch c2 = new CountDownLatch(1);//计数器为1
        CountDownLatch c3 = new CountDownLatch(1);//计数器为1

        //t1的计数器c1为0,t1执行;t2的计数器减1
        Thread t1 = new Thread(new runThread(c1, c2));

        //t2的计数器c2为0时,t2执行;t3的计数器c3减1
        Thread t2 = new Thread(new runThread(c2, c3));

        //t3的计数器c3为0时,t3执行.
        Thread t3 = new Thread(new runThread(c3, c3));

        t1.start();
        t2.start();
        t3.start();
    }

    static class runThread implements Runnable {
        private CountDownLatch c1;
        private CountDownLatch c2;

        public runThread(CountDownLatch c1, CountDownLatch c2) {
            this.c1 = c1;
            this.c2 = c2;
        }

        @Override
        public void run() {
            try {
                //计数为0才可以执行
                c1.await();
                System.out.println("thread start:" + Thread.currentThread().getName());
                //后一线程计数器减少
                c2.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

执行结果截图:

5.3 思路3&代码  

 思路3【使用单个线程池】代码示例:

public class Test3 {

    public static void main(String[] args) {
        final Thread t1 = new Thread(() -> System.out.println("thread start T1:"),"T1");
        final Thread t2 = new Thread(() -> System.out.println("thread start T2:"),"T2");
        final Thread t3 = new Thread(() -> System.out.println("thread start T3:"),"T3");

        //创建一个单线程化的线程池,以此保证线程顺序执行.
        ExecutorService executor = Executors.newSingleThreadExecutor();
        
        //执行线程
        executor.submit(t1);
        executor.submit(t2);
        executor.submit(t3);
        //关闭线程池
        executor.shutdown();
    }
}

执行结果截图:

        综合就是我此次所提供的三种思路,你们会更倾向哪一种实现方式呢?欢迎评论区交流。

        以上三种思路都有各自巧妙之处,对你们而言,还是有很好的借鉴意义,同时也鼓励大家能发挥自己的才能,脑通出更多额解题思路,只要能解题不论方法简单困难,能解题的都是一种突破。

6. 热文推荐🔥

  1. 浅谈你对单例类中使用volatile关键字的理解
  2. Mysql分页 vs Oracle分页 对比分析
  3. Java 如何实现手动连接数据库(MySQL或Oracle)?
  4. Java 如何实现获取客户端公网IP地址?
  5. 为什么print和println输出java对象时会打印内存地址?
  6. 如何解决springboot拦截器@Autowried注入为空问题?
  7. MyBatis中的discriminator鉴别器如何使用?
  8. 如何快速手撕单例类?一文教会你
  9. 如何保证三个线程按顺序执行?不懂我教你
  10. 简谈你对synchronized关键字的使用

7. 最后🔥

🏆本文收录于《Java进阶实战》,需要的小伙伴可以进去瞅瞅。

本专栏致力打造最硬核Java进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。

       我是bug菌,一名CSDN / 阿里云 / 华为云 / 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者,全网粉丝合计10w+,硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!一起学习,一起变强。

关注公众号,获取最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等硬核资源

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

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

相关文章

仪表板展示 | DataEase看世界:数据呈现世界油价变化

背景介绍 最近几个月,全球能源市场一直处于动荡不安的状态,与石油相关的新闻也非常频繁。2023年2月10日,面对西方多轮限价举措,俄罗斯副总理亚历山大诺瓦克宣布,俄罗斯将在3月把每日原油产量下调50万桶。目前&#xf…

FOFA-攻防挑战

记录一下中途短暂的辉煌时刻 辉煌一刻谁都有,别拿一刻当永久 在昨天初尝战果之后,今天又习惯性的打开 https://vulfocus.cn/ 发现今天还有挑战赛,按捺不住躁动的心,又开始了学习。今天主要拿下的是这四个镜像,同时我也会对我了解…

前端SKU一站式解决方案 - Geek-SKU

因为业务需要且市场上的UI框架与插件市场内没有简易的用法并且不够全面萌生便了自己写一个SKU组件的想法,于是Geek-SKU便应运而生。 现在的SKU组件已支持vue、uniapp,支持带图SKU、主题色设置、自动选择低价SKU、自动展示价格区间等,让您更便…

浏览器自动填充但是数据为空的问题

问题背景 公司项目中登录页为了方便,需要允许浏览器自动填充账号密码。这个在很多项目都很常见,但是测试中出现了这样一个问题:视觉上已经自动填充账号密码, 但是当点击密码的小眼睛或者点击登录时,会清空掉填充的数据…

火爆全网,性能测试-全链路压测实战总结,从需求到实战...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 流程导图 梳理阶段…

SpringBoot+Vue 的家政服务管理平台+数据库(附源码)

文章目录 1. 背景2.主要技术3. 可行性分析4.系统设计5系统的详细设计与实现5.1前台模块设计5.2后台功能模块 源码下载地址 1. 背景 本系统主要是设计出家政服务管理平台,基于B/S构架,后台数据库采用了Mysql,可以使数据的查询和存储变得更加有…

Linux函数库管理

文章目录 Linux函数库管理动态与静态函数库静态函数库动态函数库 ldconfig与 /etc/ld.so.confldconfig使用案例 程序的动态函数库解析:lddldd使用案例 校验软件的正确性常见的校验软件有哪些?使用案例 Linux函数库管理 在 Linux 操作系统中,…

【算法竞赛进阶指南】141.周期 题解 KMP 最小循环节

题目描述 一个字符串的前缀是从第一个字符开始的连续若干个字符,例如 abaab 共有 5 5 5 个前缀,分别是 a,ab,aba,abaa,abaab。 我们希望知道一个 N N N 位字符串 S S S 的前缀是否具有循环节。 换言之…

7.Ansible Modules介绍

什么是Ansible Modules? Ansible模块根据其功能分为不同的组,每个模块提供了一些功能,可以直接使用。 模块官方文档: https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html 系统模块是要在系统级别执行的操作,例如修改系统上的用户…

Springboot +spring security,认证方式---Form表单认证的实现(三)

一.简介 这篇文章来学习下security的认证方式其中的Form表单认证 二.Spring Security的认证方式 2.1什么是认证 认证: 就是用来判断系统中是否存在某用户,并判断该用户的身份是否合法的过程,解决的其实是用户登录的问题。认证的存在,是为…

Spring Boot 如何实现异步消息处理

Spring Boot异步消息处理 在现代应用程序中,异步消息处理是一项至关重要的任务。它可以提高应用程序的性能、可伸缩性和可靠性,同时也可以提供更好的用户体验。Spring Boot提供了多种方式来实现异步消息处理,包括使用Spring AMQP、Spring Ka…

【斯歌X捷普】优秀体验官活动:全民开发的样板企业是这样炼成的

3月22日,上海斯歌与捷普共同举办了一场别出心裁的活动——“产品优秀体验官”颁奖典礼,以表彰对业务流程开发做出突出贡献的捷普员工。值得注意的是,获奖的14名流程开发人员中,有7人并非是专业的IT人员,而是来自业务岗…

搜索引擎变天了!谷歌宣布开放「生成式搜索平台」!AI 大模型颠覆搜索体验

作者 | 小戏、兔子酱 搜索引擎,可能真的要变天了! Google 终于要迎来它 25 年来最大的改变,谷歌宣布了开始内测开放【生成式搜索平台(Search Generative Experience,SGE)】,并逐步舍弃那些甚至是…

Linux中与中断相关的内核数据结构

【摘要】本文树妖详细讲解了Linux中与中断相关的内核数据结构及其内部联系。 八、中断相关的数据结构 8.1 irq_desc 用于表示IRQ描述符的结构定义如下:\linux-2.6.32.63\include\linux\irq.h struct irq_desc {unsigned int irq; //中断号unsigned int …

ipad可以使用其他品牌的手写笔吗?2023年电容笔推荐

现在,人们的生活越来越智能化,有些人已经用平板电脑取代了传统的笔记本。我发现用ipad不管是用来画画还是做笔记非常方便,但是苹果Pencil对于大多数人来说都是昂贵的。据我所知,如果仅仅是为了记录,而不是为了画画的话…

他是98年的卷王,我真的玩不过他····

现在的小年轻真的卷得过分了。前段时间我们公司来了个98年的,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天,原来这位小老弟家里…

PKI 基础知识

摘要 本白皮书介绍了加密和公钥基本结构(PKI)的概念和使用 Microsoft Windows 2000 Server 操作系统中的证书服务的基础知识。如果您还不熟悉加密和公钥技术,先阅读本白皮书将有助于理解 Windows 2000 Web 站点上有关这些主题的其它技术白皮书。 引言 Microsoft …

玩转VLAN间路由,教你3个好方法

我的网工朋友大家好啊 在现实网络中,经常会遇到需要跨VLAN相互访问的情况。 很多网工通常会选择一些方法,来实现不同VLAN间主机的相互访问,例如单臂路由。 但是,单臂路由技术中由于存在一些局限性,比如带宽、转发效…

NodeJS基础到入门EXPS⑥

文章目录 ✨文章有误请指正,如果觉得对你有用,请点三连一波,蟹蟹支持😘前言Express框架 Router路由NEST 方法路由端点使用回调函数数组处理路由使用混合使用函数和函数数组处理路由中间件的分类及用法 1、应用级中间件 2、路…

使用 python 制作自动填写问卷星问卷调查程序

目录 前言环境:代码展示尾语 💝 前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 你的问卷星任务还没做完吗?今天教你如何快速把问卷星调查任务给完成。 环境: anaconda5.2.0(python3.6.8) 编辑器: p…