Version: Next

常用辅助类

  • CountDownLatch
  • CyclicBarrier
  • Semaphore

CountDownLatch (计减闭锁)

减法计数器辅助类

  • 构造方法要求传入一个int类型的初始值
  • 执行countDown()方法,就减1
  • await()方法,等待计数器归零
  • 当计数器归零,再执行之后的语句,执行某操作,用于等待所有线程执行完毕后
// 减法计数器
public class Demo01CountDownLatch {
public static void main(String[] args) throws InterruptedException {
// 总数是16,倒计时
CountDownLatch countDownLatch = new CountDownLatch(16);
for (int i = 0; i < 16; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "开始跑了");
// countDown()方法执行-1
countDownLatch.countDown();
}, "Thread " + i).start();
}
//等待计数器归零
countDownLatch.await();
System.out.println("线程全跑了,溜了溜了");
}
}
Thread 0开始跑了
Thread 2开始跑了
Thread 3开始跑了
Thread 1开始跑了
Thread 4开始跑了
Thread 5开始跑了
Thread 6开始跑了
Thread 7开始跑了
Thread 8开始跑了
Thread 9开始跑了
Thread 10开始跑了
Thread 11开始跑了
Thread 12开始跑了
Thread 13开始跑了
Thread 14开始跑了
Thread 15开始跑了
线程全跑了,溜了溜了

CyclicBarrier(循环屏障)

加法计数器

  • 构造方法接收
    • int类型的数
    • 一个Runnable接口的实现类

CyclicBarrier和CountDownLatch非常类似,它也可以实现多个线程之间的计数等待,但它的功能比CountDownLatch更加复杂和强大。主要应用场景和CountDownLatch类似

CyclicBarrier的字面意思是可循环(Cyclic)的屏障(Barrier)。他要完成的事是,让一组线程达到一个屏障(也叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活

CyclicBarrier的默认构造方法为CyclicBarrier(int parties),其参数表示屏蔽拦截的线程数,每个线程调用await()方法告诉CyclicBarrier自己已经到达了屏障,然后当前线程被阻塞

例:集齐七龙珠

public class Demo02CyclicBarrier {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("集齐了7颗龙珠,召唤神龙");
});
for (int i = 1; i <= 7; i++) {
final int tempI = i;
new Thread(() -> {
System.out.println("收集了第" + tempI + "号龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, "Thread" + i).start();
}
}
}
收集了第1号龙珠
收集了第2号龙珠
收集了第3号龙珠
收集了第4号龙珠
收集了第5号龙珠
收集了第6号龙珠
收集了第7号龙珠
集齐了7颗龙珠,召唤神龙

Semaphore(信号量)

信号量

synchronized和ReentrantLock都是一次只允许一个线程访问某个资源,Semaphore(信号量)可以指定多个线程同时访问某个资源

  • 构造方法要求传入一个int类型的参数,默认线程数量(可用资源数目)
  • 可以用来做限流、控制最大线程数
  • acquire()——拿到一个资源
  • release()——释放

例:6辆车,3个车位

public class Demo03Semaphore {
public static void main(String[] args) {
// 假设为停车位
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
// acquire 得到
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "抢到了车位");
//占用两秒
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
// release 释放
}, "Thread" + i).start();
}
}
}
Thread0抢到了车位
Thread2抢到了车位
Thread1抢到了车位
--------------- 等待两秒
Thread2离开了车位
Thread0离开了车位
Thread1离开了车位
Thread4抢到了车位
Thread3抢到了车位
Thread5抢到了车位
--------------- 等待两秒
Thread4离开了车位
Thread3离开了车位
Thread5离开了车位