引言:更多相关请看 JAVA并发编程系列
CountDownLatch减少计数
含义:让一些线程阻塞直到另外一些完成后才被唤醒。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞.其他线程调用countDown方法计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0,因调用await方法被阻塞的线程会被唤醒,继续执行。
案例
class CountDownLatchDemo {
public static void main(String[] args) throws Exception {
// closeDoor();
destroySixCountry();
}
/**
* 关门案例
* 班长必须等六位同学离开教室才能锁教室门
* @throws InterruptedException
*/
private static void closeDoor() throws InterruptedException {
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班长锁门离开教室");
}
/**
* 秦灭六国案例
* 秦朝必须灭掉六国才能统一天下
* @throws InterruptedException
*/
private static void destroySixCountry() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
final int temp = i;
new Thread(() -> {
System.out.println(CountryEnum.forEach(temp).getName() + "\t" + "被灭");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t秦国统一天下");
}
}
@Getter
@AllArgsConstructor
// @Data 不支持使用在枚举里面
enum CountryEnum {
/**
* 六国枚举
*/
ONE(1, "齐"),TWO(2, "楚"),THREE(3, "燕"),FOUR(4, "赵"),FIVE(5, "魏"), SIX(6, "韩");
private Integer code;
private String name;
public static CountryEnum forEach(int index) {
CountryEnum[] countryEnums = CountryEnum.values();
for (CountryEnum countryEnum : countryEnums) {
if (index == countryEnum.getCode()) {
return countryEnum;
}
}
return null;
}
}
CyclicBarrier循环栅栏
CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法。
案例
/**
* 集齐7颗龙珠就能召唤神龙
*/
class CyclicBarrierDemo {
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有两个方法,acquire获取和release释放
*/
class SemaphoreDemo {
public static void main(String[] args) {
// 同时最多只有3辆车能抢到车位,其它车辆必须等到有空闲车位时才能抢车位。
//模拟3个停车位
Semaphore semaphore = new Semaphore(3);
//模拟8部汽车
for (int i = 1; i <= 8; i++) {
new Thread(() -> {
try {
//抢到资源
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t抢到车位");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t 停0.5秒离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放资源
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
效果: