一. CountDownLatch
CountDownLatch:
他允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。
他是线程一直减减的
CountDownLatch主要有两个方法,
1.当一个或多个线程调用await()方法时,调用线程会被阻塞。
2.其他线程调用countDown()方法会将计数器减1,当计数器的值变为0时,
因调用await()方法被阻塞的线程才会被唤醒,继续执行
案例:饭店吃饭
public static void main(String[] args) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(6); //默认必须给值
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 吃完饭,离开饭店");
countDownLatch.countDown(); //客人一个一个走
}, String.valueOf(i)).start();
}
countDownLatch.await(); //老板需要等待客人离开后再走
System.out.println(Thread.currentThread().getName() + "\t ##老板,关门回家");
}
运行结果
总结:
适用于,要先完成某些前置任务,才会触发后续任务的案例。
二. CyclicBarrier
CyclicBarrier:
可循环(Cyclic)使用的屏障。
让一组线程到达一个屏障(也可叫同步点)时被阻塞,
直到最后一个线程到达屏障时,屏障才会开门,
所有被屏障拦截的线程才会继续干活,线程进入屏障通过CycliBarrier的await()方法
他是线程一直加加的
案例:收集七龙珠,召唤神龙。
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {System.out.println("### 成功召唤出神龙。。。");});
for (int i = 1; i <= 7; i++) {
final int temp = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 收集到第 " + temp + " 颗龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
运行结果
总结:
也适用于,要先完成某些前置任务,才会触发后续任务的案例。
三. Semaphore
Semaphore:
信号量主要用于两个目的,一个是用于多个共享资源的互斥作用,
另一个用于并发线程数的控制
适用于秒杀,小米秒杀手机使用Semaphore。
可以代替 Synchronize 和 Lock
案例:抢车位
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); //模拟3个停车位
//6辆车抢车位
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
//抢占车位
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "### 抢到车位");
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "### 停车3秒后离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放车位
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
运行结果