CountDownLatch
理解: 可以把CountDownLatch看成火箭发射倒计时,也就是当其他条件满足的时候,才开始某个线程的运行.
例子:比如放学了,班长必须等全部同学走完啦,才可以关门,也就是说关门的这个操作,必须放在最后一步.
先看下不用CountDownLatch的的结果
public class SpinDemo {
public static void main(String[] args) {
for (int i = 0; i <6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"上完自习,离开教室 ");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"班长关门走人");
}
}
2上完自习,离开教室
main班长关门走人
0上完自习,离开教室
1上完自习,离开教室
4上完自习,离开教室
3上完自习,离开教室
5上完自习,离开教室
可以看到,还没有等其他同学走的时候就已经关门…那么如何避免呢
public class SpinDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i <6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"上完自习,离开教室 ");
countDownLatch.countDown();//走一个减一
},String.valueOf(i)).start();
}
countDownLatch.await(); //班长等着,啥时候6清0啦 才能走
System.out.println(Thread.currentThread().getName()+"班长关门走人");
}
}
0上完自习,离开教室
5上完自习,离开教室
1上完自习,离开教室
2上完自习,离开教室
3上完自习,离开教室
4上完自习,离开教室
main班长关门走人
这里添加个枚举
package com.disney.demo;
import javax.xml.bind.Element;
public enum ConntryEnum {
ONE(0,"齐"),
TOW(1,"楚"),
THREE(2,"燕"),
FOUR(3,"赵"),
FIVE(4,"魏国"),
SIX(5,"秦国");
private Integer CountryId;
private String CountryName;
ConntryEnum(Integer countryId, String countryName) {
CountryId = countryId;
CountryName = countryName;
}
public Integer getCountryId() {
return CountryId;
}
public void setCountryId(Integer countryId) {
CountryId = countryId;
}
public String getCountryName() {
return CountryName;
}
public void setCountryName(String countryName) {
CountryName = countryName;
}
public static ConntryEnum forConntryEnum(int index){
ConntryEnum[] values = ConntryEnum.values();
for (ConntryEnum conntryEnum : values){
if (index== conntryEnum.getCountryId()){
return conntryEnum;
}
}
return null;
}
}
public class SpinDemo {
public static void main(String[] args) throws InterruptedException {
Integer countryId = ConntryEnum.ONE.getCountryId();
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i <6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"被消灭啦");
countDownLatch.countDown();//走一个减一
},ConntryEnum.forConntryEnum(i).getCountryName()).start();
}
countDownLatch.await(); //班长等着,啥时候6清0啦 才能走
System.out.println(Thread.currentThread().getName()+"秦国统一六国");
}
}
齐被消灭啦
楚被消灭啦
燕被消灭啦
赵被消灭啦
魏国被消灭啦
秦国被消灭啦
main秦国统一六国
CyclicBarrier
CyclicBarrier和CountDownLatch最大的不同是CountDownLatch是倒计时而CyclicBarrier是增加到某个节点的时候,开始程序的运行.
比如: 收集7颗龙珠,召唤神龙
public enum ConntryEnum {
ONE(0,"一龙珠"),
TOW(1,"二龙珠"),
THREE(2,"三龙珠"),
FOUR(3,"四龙珠"),
FIVE(4,"五龙珠"),
SIX(5,"六龙珠"),
SEVEN(6,"七龙珠");
private Integer CountryId;
private String CountryName;
ConntryEnum(Integer countryId, String countryName) {
CountryId = countryId;
CountryName = countryName;
}
public Integer getCountryId() {
return CountryId;
}
public void setCountryId(Integer countryId) {
CountryId = countryId;
}
public String getCountryName() {
return CountryName;
}
public void setCountryName(String countryName) {
CountryName = countryName;
}
public static ConntryEnum forConntryEnum(int index){
ConntryEnum[] values = ConntryEnum.values();
for (ConntryEnum conntryEnum : values){
if (index== conntryEnum.getCountryId()){
return conntryEnum;
}
}
return null;
}
}
public class SpinDemo {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println(Thread.currentThread().getName() + "出来吧神龙");
}
);
for (int i = 0; i <= 6; i++) {
new Thread(() -> {
System.out.println("找到了" + Thread.currentThread().getName());
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, ConntryEnum.forConntryEnum(i).getCountryName()).start();
}
}
}
Semaphore
Semaphore主要是解决多个线程抢占多个资源的问题.
比如旅游的时候,只有30个车位,但是此时却有50个人,此时一般情况就是等有人释放啦,排队进行等待.
构造方法
public class SpinDemo {
public static void main(String[] args) throws InterruptedException {
//3个车位
Semaphore semaphore = new Semaphore(3);
//6个人
for (int i = 0; i <6 ; i++) {
new Thread(()->{
try {
semaphore.acquire(); // 我抢到一个资源
System.out.println(Thread.currentThread().getName()+"抢到车位");
Thread.sleep(3000); //我停车三秒
System.out.println(Thread.currentThread().getName()+"释放车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();//释放车位
}
},String.valueOf(i+1)).start();
}
}
}
1抢到车位
3抢到车位
2抢到车位
1释放车位
3释放车位
2释放车位
4抢到车位
6抢到车位
5抢到车位
6释放车位
5释放车位
4释放车位