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釋放車位