【并发编程】java并发编程之线程同步(CountDownLatch、CyclicBarrier)

//线程2

Thread t2 = new Thread(() -> {

hello();

});

t2.start();

try {

t1.join();

t2.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“主函数执行完毕。。。。。。。。。”);

}

结果如下:

为什么join(),可以实现线程同步呢?join()源码如下:

很明显,这里使用while做了循环等待,让线程不往下执行,达到线程同步(等待)的效果。

然而我们平时的开发过程中基本不会这么创建线程,一般都是使用线程池,那在使用线程池的情况下如何让线程实现同步呢?

我们先试试自己写一个方法让它实现同步,代码如下:

public static void hello(){

String name = Thread.currentThread().getName();

try {

System.out.println(“线程:”+name+" 休眠开始。。。。。。。。。。。。");

Thread.sleep(1000);

System.out.println(“线程:”+name+" 休眠结束。。。。。。。。。。。。");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

// 计数器初始化为2

AtomicInteger count = new AtomicInteger(2);

executor.execute(() ->{

hello();

count.decrementAndGet();

});

executor.execute(() ->{

hello();

count.decrementAndGet();

});

//等待两个线程执行完毕

while(count.get() != 0){

}

System.out.println(“我是在两个线程执行之后才执行的内容”);

}

count:用于统计线程执行的数量,线程执行-1;AtomicInteger:原子类,可以在多线程中保证共享变量的安全。

decrementAndGet:自减并返回自减以后的结果(原子操作)。

while:线程同步的重点:这里主要是让主线程处于循环状态,直到count被减为0,也就意味着两个子线程都已执行完毕。

但是我不推荐这么做,为什么呢?因为java SDK给我们提供了现成的方法,我们为啥还要自己去手动实现呢?下面我们就来看看 CountDownLatch是如何实现线程同步:

// 创建2个线程的线程池

private static Executor executor = Executors.newFixedThreadPool(2);

public static void hello(){

String name = Thread.currentThread().getName();

try {

System.out.println(“线程:”+name+" 休眠开始。。。。。。。。。。。。");

Thread.sleep(1000);

System.out.println(“线程:”+name+" 休眠结束。。。。。。。。。。。。");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

//这里需要注意一点,那就是实例化CountDownLatch的初始大小,一定要和你需要等待线程的数量相同,

//小了会导致等待的线程提前执行。

//大了会导致线程一直处于无限循环当中

CountDownLatch countDownLatch = new CountDownLatch(2);

executor.execute(() ->{

hello();

countDownLatch.countDown();

});

executor.execute(() ->{

hello();

countDownLatch.countDown();

});

//等待两个线程执行完毕

try {

countDownLatch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“我是在两个线程执行之后才执行的内容”);

}

为了效果明显,我特意在hello方法让线程休眠1秒。

countDownLatch:实现线程同步的关键,实例化一个需要等待的线程数量

countDownLatch.countDown():等待线程数-1。

countDownLatch.await();让主线程处于等待状态,直到等待的线程被减为0(注意:这里必须要做异常捕获线程中断的异常:(InterruptedException);

上面代码结果如下:

这里需要注意一点:CountDownLatch的初始大小是不会被重置的,所以使用这个解决方案的时候需要手动重置CountDownLatch线程等待的初始大小。

实现原理:

其实查看源码,他的实现方式和我之前使用的while类似,他这里用了for的无限循环,直到等待的线程被减为0;

那有没有不需要重新设置线程等待的工具类呢?肯定是有的,那就是接下来要说的:CyclicBarrier

CyclicBarrier

主要通过线程回调来实现线程等待,这里的实现方式稍微做了一下修改:

// 创建3个线程的线程池,其中一个线程用于回调处理主线程的事情

private static Executor executor = Executors.newFixedThreadPool(3);

public static void hello(){

String name = Thread.currentThread().getName();

try {

System.out.println(“线程:”+name+" 休眠开始。。。。。。。。。。。。");

Thread.sleep(1000);

System.out.println(“线程:”+name+" 休眠结束。。。。。。。。。。。。");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

//这里需要注意一点,那就是实例化CountDownLatch的初始大小,一定要和你需要等待线程的数量相同,

//小了会导致等待的线程提前执行。

//大了会导致线程一直处于无限循环当中

final CyclicBarrier barrier = new CyclicBarrier(2, ()->{ executor.execute(()->printAfter()); });

executor.execute(() ->{

hello();

try {

barrier.await();

} catch (Exception e) {

e.printStackTrace();

}

});

executor.execute(() ->{

hello();

try {

barrier.await();

} catch (Exception e) {

e.printStackTrace();

}

});

}

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

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

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

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

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

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

img

最后

光给面试题不给答案不是我的风格。这里面的面试题也只是凤毛麟角,还有答案的话会极大的增加文章的篇幅,减少文章的可读性

Java面试宝典2021版

最常见Java面试题解析(2021最新版)

2021企业Java面试题精选

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

最常见Java面试题解析(2021最新版)

[外链图片转存中…(img-oOKbq4Ib-1713412369227)]

[外链图片转存中…(img-oZHhxmJL-1713412369227)]

2021企业Java面试题精选

[外链图片转存中…(img-8D78YawP-1713412369227)]

[外链图片转存中…(img-YIKkpeh8-1713412369228)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值