1. 限制
JUC提供了几个比较常用的并发工具类:CountDownLatch extend AQS、CyclicBarrier 包含 Lock对象、Semaphore extend AQS
1.1 CountDownLatch
countdownlatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作,执行完毕再执行。不可重置/不能重复使用从命名可以解读到 countdown 是倒数的意思,类似于我们倒计时的概念。countdownlatch 提供了两个方法,一个是 countDown,一个是 await, countdownlatch 初始化的时候需要传入一个整数,在这个整数倒数到 0 之前,调用了 await 方法的程序都必须要等待,然后通过 countDown 来倒数。
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(3);
new Thread(()->{
System.out.println(""+Thread.currentThread().getName()+"-执行中");
countDownLatch.countDown();
System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
},"t1").start();
new Thread(()->{
System.out.println(""+Thread.currentThread().getName()+"-执行中");
countDownLatch.countDown();
System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
},"t2").start();
new Thread(()->{
System.out.println(""+Thread.currentThread().getName()+"-执行中");
countDownLatch.countDown();
System.out.println(""+Thread.currentThread().getName()+"-执行完毕");
},"t3").start();
countDownLatch.await();//等待执行完毕,类似Thread.join功能
System.out.println("所有线程执行完毕");
}
//从代码的实现来看,有点类似 join 的功能,但是比 join 更加灵活。CountDownLatch 构造函
//数会接收一个 int 类型的参数作为计数器的初始值,当调用 CountDownLatch 的 countDown
//方法时,这个计数器就会减一。
//通过 await 方法去阻塞去阻塞主流程
//凡事涉及到需要指定某个任务在执行之前,要等到前置任务执行完毕之后才执行的场景,都可以使用 CountDownLatch
1.2 CyclicBarrier
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门 , 所有被屏障拦截的线程才会继续工 作 。
1.2.1 使用场景
当存在需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用 CyclicBarrier。可重置reset,重复使用
public class DataImportThread extends Thread{
private CyclicBarrier cyclicBarrier;
private String path;
public DataImportThread(CyclicBarrier cyclicBarrier, String path) {
this.cyclicBarrier = cyclicBarrier;
this.path = path;
}
@Override
public void run() {
System.out.println("开始导入:"+path+"位置的数据");
try {
cyclicBarrier.await();//阻塞
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
//CycliBarrierDemo
public class CycliBarrierDemo extends Thread{
@Override
public void run() {
System.out.println("开始进行数据分析");
}
public static void main(String[] args) {
CyclicBarrier cycliBarrier=new
CyclicBarrier(3,new CycliBarrierDemo());
new Thread(new DataImportThread(cycliBarrier,"file1")).start();
new Thread(new DataImportThread(cycliBarrier,"file2")).start();
new Thread(new DataImportThread(cycliBarrier,"file3")).start();
}
}
1.3 Semaphore
semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。可释放release,然后重复使用
public class Test {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(5);
for(int i=0;i<10;i++){
new Car(i,semaphore).start();
}
}
static class Car extends Thread{
private int num;
private Semaphore semaphore;
public Car(int num, Semaphore semaphore) {
this.num = num;
this.semaphore = semaphore;
}
public void run(){
try {
semaphore.acquire();//获取一个许可
System.out.println("第"+num+"占用一个停车位");
TimeUnit.SECONDS.sleep(2);
System.out.println("第"+num+"俩车走喽");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}