Java并发工具类介绍,做Java程序员真的没有春天吗

4、Exchanger,用于两个线程之间的数据交换。

介绍

==

1)CountDownLatch


CountDownLatch,类似于计数器的方式,用于等待一个或多个线程执行完操作开始自身代码的执行。

其构造函数接收一个int类型的整数作为计数器而使用,例如如果想等待N个线程执行完毕就传入N,当每调用一次countDown函数,表示某一个线程执行完毕。实际上,这个N并不

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

是与线程绑定,也就是说并不是一定和线程的数量一致,只需要countDown函数执行N次,当前等待的线程就会开始执行。下面列出具体代码:

public static class CountDownLatchTest {

static CountDownLatch countDownLatch = new CountDownLatch(2);

public static void main(String[] args) {

new Thread(new Runnable() {

@Override

public void run() {

SleepUtils.second(2);

System.out.println(“1”);

countDownLatch.countDown();

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

SleepUtils.second(4);

System.out.println(“2”);

countDownLatch.countDown();

}

}).start();

try {

// 主线程开始等待

countDownLatch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“3”);

}

}

输出如下:

1

2

3

Process finished with exit code 0

注意点

1、如果传入的参数大于2,那么主线程将会一直等待。

2、计数器必须大于0,如果为0,调用await方法不会阻塞当前线程。

应用场景

当遇到一个比较耗时的计算量较大的任务时,我们则可以考虑使用多线程来操作,将一个大任务拆分成多个小任务(一个任务相当于一个线程),当每个小任务执行完毕返回结果后,再由某一主线程对结果进行统计。

2)CyclicBarrier


CyclicBarrier即同步屏障,它主要功能是让一组线程达到一个屏障(也可以称为同步点)是被阻塞,直到最后一个线程达到屏障是,屏障才被打开,所有被拦截的线程才会继续执行。

其构造函数默认也是接收一个int类型的参数N作为屏障拦截的线程数量,每个线程调用await方法表示到达了屏障点,然后被阻塞。具体示例如下:

public class CyclicBarrierTest {

// 参数表示屏障拦截的线程数量, 每个线程调用 await方法,告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞

// 屏障拦截的线程数量必须和当前的线程数一致,并且都调用await方法,否则当前所有的线程都处于等待状态

static CyclicBarrier c = new CyclicBarrier(3);

public static void main(String[] args) {

new Thread(new Runnable() {

@Override

public void run() {

try {

System.out.println("1—1 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

c.await();

} catch (BrokenBarrierException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("1—2 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("2—1 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

try {

c.await();

} catch (BrokenBarrierException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("2—2 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

}

}).start();

SleepUtils.second(2);

System.out.println("3—1 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

try {

c.await();

} catch (BrokenBarrierException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("3—2 " + new SimpleDateFormat(“HH:mm:ss”).format(new Date()));

}

}

输出如下:

1—1 17:05:01

2—1 17:05:01

3—1 17:05:03

3—2 17:05:03

1—2 17:05:03

2—2 17:05:03

Process finished with exit code 0

注意点

1、构造函数中的N必须为线程的总数,当最后一个线程调用await方法(到达屏障)时,屏障才会打开,被阻塞的线程才会执行,这里的N表示的含义和CountDownLatch传入的N是不一样的。

2、我们发现,当所有线程都到达屏障时,当屏障打开,接下来会优先执行哪个线程呢?如上代码答案是不确定的。但是CyclicBarrier为我们提供了一个更高级的用法,即构造函数还支持传递一个Runnable对象,当屏障打开时,优先执行Runnable中的run方法。(这一功能十分强大,完全可以替代CountDownLatch了)

应用场景

同CountDownLatch

与CountDownLatch区别:

CountDownLatch计数器只能使用一次,而CyclicBarrier的计数器可以使用 reset方法重置,所以适合更复杂的业务场景。

3)Semaphore


Semaphore即信号量,主要用来控制并发访问特定资源的线程数量,协调各个线程合理使用公共资源。

构造函数同样也是接收一个int类型的参数N作为入参,用来限制访问某一公共资源最大的线程并发数,通过acquire来获取许可证,release释放许可证。

具体示例如下:

public class SemaphoreTest {

private static final int THREAD_COUNT = 6;

private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);

private static Semaphore semaphore = new Semaphore(2);

public static void main(String[] args) {

for (int i = 0; i < THREAD_COUNT; i++) {

threadPool.execute(new MyRunnable(i + 1));

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值