CountDownLatch
CountDownLatch 是在 java 1.5 被引入。
CountDownLatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。
CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被阻塞。其他线程调用countDown 方法计数器减1 (调用 countDown 方法时线程不会阻塞),当计数器的值变为 0 ,因调用 await 方法被阻塞的线程会被唤醒继续执行。
示例
假如教室里面有三个学生在上自习,三个人走了以后班长才能走然后把门关上。
enum Man{
ONE(1,"张三"),TWO(2,"李四"),TREEE(3,"王五");
private int index;
private String name;
public int getIndex() {
return index;
}
public String getName() {
return name;
}
private Man(int index, String name) {
this.index = index;
this.name = name;
}
public static Man getIndex(int index) {
Man[] mans = Man.values();
for(Man m : mans) {
if(m.getIndex() == index) {
return m;
}
}
return null;
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
for (int i = 1; i <=3; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 离开教室...");
},Man.getIndex(i).getName()).start();
}
System.out.println(Thread.currentThread().getName()+"最后离开教室关门...");
}
}
运行结果
发现结果并不是我们想象中的那样,于是开始加上锁机制。
改进代码
// 枚举类不变,主方法加锁
public class CountDownLatchDemo {
public static final int COUNT = 3;
public static void main(String[] args) throws InterruptedException {
// 上锁
CountDownLatch cdl = new CountDownLatch(COUNT);
for (int i = 1; i <=3; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 离开教室...");
cdl.countDown(); // 数字-1
},Man.getIndex(i).getName()).start();
}
cdl.await(); // 等待,数字变为 0 时自动唤醒
System.out.println(Thread.currentThread().getName()+"最后离开教室关门...");
}
}
运行结果
CyclicBarrier
CyclicBarrier 是在 java 1.5 被引入。
其字面意思是循环栅栏,CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过 CyclicBarrier 的 await() 方法。
示例
public class CyclicBarrierDemo {
public static final int COUNT = 3;
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cb = new CyclicBarrier(3,()->{
System.out.println("班长最后离开教室关门...");
});
for (int i = 1; i <=3; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 离开教室...");
try {
cb.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},Man.getIndex(i).getName()).start();
}
}
}
运行结果
Semaphore
这个类大家一看都应该知道,是信号量的意思。在多线程编程中,特别是秒杀系统被广泛使用,他可以实现多个线程抢占多份资源安全的功能。
信号量的主要用户两个目的,一个是用于多喝共享资源的相互排斥使用,另一个用于并发资源数的控制。
示例
import java.util.concurrent.Semaphore;
/* 模拟6辆车抢三个停车位 */
public class SemaphoreDemo {
public static void main(String[] args) {
// 三个停车位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
// 抢资源
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+" 抢到车位");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+" 3秒后离开");
// 放弃资源
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();;
}
}
}