保证多线程顺序执行,四种方案,你知道几种?

文章介绍了使用Java实现线程顺序执行的不同方法,包括Thread.join、CountDownLatch、ExecutorService的单线程池以及CompletableFuture,展示了这些工具在控制线程执行顺序上的应用和优势。
摘要由CSDN通过智能技术生成

if (delay <= 0) {

break;

}

//每次最多等待delay毫秒时间后继续争抢对象锁,获取锁后继续从这里开始的下一行执行,

//也可能提前被notify() /notifyAll()唤醒,造成delay未一次性消耗完,

//会继续执行while继续wait(剩下的delay)

wait(delay);

// 这个变量now起的不太好,叫elapsedMillis就容易理解了

now = System.currentTimeMillis() - base;

}

}

}

下面我们使用join方法来实现线程的顺序执行。

public class ThreadDemo {

public static void main(String[] args) {

final Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println(“线程1”);

}

});

final Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

try {

//等待线程t1执行完成后

//本线程t2 再执行

t1.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“线程2”);

}

});

Thread t3 = new Thread(new Runnable() {

@Override

public void run() {

try {

//等待线程t2执行完成后

//本线程t3 再执行

t2.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“线程3”);

}

});

t3.start();

t2.start();

t1.start();

}

}

运行结果:

线程1

线程2

线程3

不管你运行多少次上面这段代码,结果始终不变,所以,我们就解决了多个线程按照顺序执行的问题了。

下面我们来看看另外一种方案:CountDownLatch。

方案二

===

我们先来说一下CountDownLatch,然后再来使用CountDownLatch是怎么解决多个线程顺序执行的。

CountDownLatch是一种同步辅助,在AQS基础之上实现的一个并发工具类,让我们多个线程执行任务时,需要等待线程执行完成后,才能执行下面的语句,之前线程操作时是使用 Thread.join方法进行等待 。

CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。它相当于是一个计数器,这个计数器的初始值就是线程的数量,每当一个任务完成后,计数器的值就会减一,当计数器的值为 0 时,表示所有的线程都已经任务了,然后在 CountDownLatch 上等待的线程就可以恢复执行接下来的任务。

下面我们就用CountDownLatch来实现多个线程顺序执行:

import java.util.concurrent.CountDownLatch;

/**

*

* @author 小蒋学

*  CountDownLatch 实现多个线程顺序执行

*/

public class ThreadDemo {

public static void main(String[] args) {

CountDownLatch countDownLatch1 = new CountDownLatch(0);

CountDownLatch countDownLatch2 = new CountDownLatch(1);

CountDownLatch countDownLatch3 = new CountDownLatch(1);

Thread t1 = new Thread(new Work(countDownLatch1, countDownLatch2),“线程1”);

Thread t2 = new Thread(new Work(countDownLatch2, countDownLatch3),“线程2”);

Thread t3 = new Thread(new Work(countDownLatch3, countDownLatch3),“线程3”);

t1.start();

t2.start();

t3.start();

}

static class Work implements Runnable {

CountDownLatch cOne;

CountDownLatch cTwo;

public Work(CountDownLatch cOne, CountDownLatch cTwo) {

super();

this.cOne = cOne;

this.cTwo = cTwo;

}

@Override

public void run() {

try {

cOne.await();

System.out.println("执行: " + Thread.currentThread().getName());

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

cTwo.countDown();

}

}

}

}

运行结果:

执行: 线程1

执行: 线程2

执行: 线程3

关于CountDownLatch实现多个线程顺序执行就这样实现了,下面我们再用线程池来实现。

方案三

===

在Executors 类中有个单线程池的创建方式,下面我们就用单线程池的方式来实现多个线程顺序执行。

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

*

* @author 小蒋学

*  CountDownLatch 实现多个线程顺序执行

*/

public class ThreadDemo {

public static void main(String[] args) {

Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println(“线程1”);

}

},“线程1”);

Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println(“线程2”);

}

},“线程2”);

Thread t3 = new Thread(new Runnable() {

@Override

public void run() {

System.out.println(“线程3”);

}

});

ExecutorService executor = Executors.newSingleThreadExecutor();

// 将线程依次加入到线程池中

executor.submit(t1);

executor.submit(t2);

executor.submit(t3);

// 及时将线程池关闭

executor.shutdown();

}

}

运行结果:

线程1

线程2

线程3

这样我们利用单线程池也实现了多个线程顺序执行的问题。下面再来说一种更牛的方案。

方案四

===

最后一种方案是使用CompletableFuture来实现多个线程顺序执行。

在Java 8问世前想要实现任务的回调,一般有以下两种方式:

  • 借助Future isDone轮询以判断任务是否执行结束,并获取结果。

  • 借助Guava类库ListenableFuture、FutureCallback。(netty也有类似的实现)

Java 8 CompletableFuture弥补了Java在异步编程方面的弱势。

在Java中异步编程,不一定非要使用rxJava,Java本身的库中的CompletableFuture可以很好的应对大部分的场景。

Java8新增的CompletableFuture则借鉴了Netty等对Future的改造,简化了异步编程的复杂性,并且提供了函数式编程的能力 。

使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。

从Java 8开始引入了CompletableFuture,它针对Future做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。

接下来我们就使用CompletableFuture来实现多个线程顺序执行。

import java.util.concurrent.CompletableFuture;

/**

*

* @author 小蒋学

*  CountDownLatch 实现多个线程顺序执行

*/

public class ThreadDemo {

public static void main(String[] args)  {

Thread t1 = new Thread(new Work(),“线程1”);

Thread t2 = new Thread(new Work(),“线程2”);

Thread t3 = new Thread(new Work(),“线程3”);

CompletableFuture.runAsync(()-> t1.start())

.thenRun(()->t2.start())

.thenRun(()->t3.start());

}

static class Work implements Runnable{

@Override

public void run() {

System.out.println("执行 : " + Thread.currentThread().getName());

}

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

知其然不知其所以然,大厂常问面试技术如何复习?

1、热门面试题及答案大全

面试前做足功夫,让你面试成功率提升一截,这里一份热门350道一线互联网常问面试题及答案助你拿offer

2、多线程、高并发、缓存入门到实战项目pdf书籍

3、文中提到面试题答案整理

4、Java核心知识面试宝典

覆盖了JVM 、JAVA集合、JAVA多线程并发、JAVA基础、Spring原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB 、Cassandra、设计模式、负载均衡、数据库、一致性算法 、JAVA算法、数据结构、算法、分布式缓存、Hadoop、Spark、Storm的大量技术点且讲解的非常深入


《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
图片转存中…(img-IEI6AKFs-1713525830100)]

3、文中提到面试题答案整理

[外链图片转存中…(img-n3kuIlSG-1713525830101)]

4、Java核心知识面试宝典

覆盖了JVM 、JAVA集合、JAVA多线程并发、JAVA基础、Spring原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB 、Cassandra、设计模式、负载均衡、数据库、一致性算法 、JAVA算法、数据结构、算法、分布式缓存、Hadoop、Spark、Storm的大量技术点且讲解的非常深入

[外链图片转存中…(img-7wx9a1Ik-1713525830101)]

[外链图片转存中…(img-rvWX2E0t-1713525830101)]

[外链图片转存中…(img-hWip7GQx-1713525830101)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值