同步工具类--能够更好控制线程之间的通讯问题
1.CountDownLatch(闭锁)
2.CyclicBarrier(栅栏)
3.Semaphore(信号量)
CountDownLatch
CountDownLatch是一个同步的辅助类,允许一个或多个线程一直等待,直到其它线程完成它们的操作。它常用的API其实就两个:await()和countDown()
CountDownLatch 例子1
小华 小杰 和小虎三兄弟相约吃饭,但是小华很墨迹啊又得梳头洗澡干啥的,就要他的两个朋友等他
public static void main(String [] args){
//定义计数器,线程等待的计数
final CountDownLatch countDownLatch=new CountDownLatch(1);
//启动一个线程相当于小华 小华在洗澡
new Thread(new Runnable() {
@Override
public void run() {
try{
//等待中。。。。
Thread.sleep(10);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("小华搞完了");
//线程计数器减一
countDownLatch.countDown();
}
}).start();
//启动两个线程相当于小华的朋友,在等待。。。
for(int i=1;i<=2;i++){
int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("朋友"+ finalI);
System.out.println(Thread.currentThread().getName()+"等待小华。。。");
try{
//线程等待,就会跳到小华的线程继续执行
countDownLatch.await();
}catch (Exception e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"出发。。。。");
}
}).start();
}
}
image.png
CountDownLatch 例子2
小华上次让他的两个朋友等了很久呀,所以这次他的两个朋友也开始搞事情,让小华等他们两个人
public static void main(String[] args) {
final CountDownLatch countDownLatch = new CountDownLatch(2);
System.out.println("小华和朋友相约吃饭。。。。");
new Thread(new Runnable() {
@Override
public void run() {
try{
System.out.println("风水轮流转,小华等待朋友。。。");
//小华等待。。的时候他的两个朋友正在搞事情
countDownLatch.await();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("两个朋友都搞完了,终于可以出发了。。。");
}
}).start();
for (int i = 1; i <= 2; i++) {
int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
try{
Thread.currentThread().setName("朋友"+finalI);
System.out.println(Thread.currentThread().getName()+"搞事情,为了给小华一个教训。。");
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+"搞完了。。");
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
image.png
countDownLanch 就是一个或者多个线程等待其他线程。。等其他线程搞完事情了,再执行被等待的线程
CyclicBarrier
栅栏嘛,就是前面有一个栏杆,就像地铁限流的时候,所有人都在等待可以通行的信号,强调的是状态,所有的线程在某个状态下停下来,等待其他的线程,当所有的线程都到达了这个状态后,再执行
还是小华 和他的两个朋友一起相约吃完饭后,宵夜 KTV 一条龙
这个状态就是大家都吃完饭
public static void main(String[] args){
final CyclicBarrier cyclicBarrier=new CyclicBarrier(3);
// new Thread(()->{ }).start();
for(int i=1;i<=3;i++){
int finalI=i;
new Thread(new Runnable() {
@Override
public void run() {
String name="小华";
try{
if(finalI==1){
name="小杰";
}else if(finalI==2){
name="小虎";
}else{
name="小华";
}
System.out.println("等"+ name+"吃完饭。。。。");
cyclicBarrier.getNumberWaiting();
cyclicBarrier.await();
System.out.println("然后一起去happy...");
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
}
image.png
Semaphore(信号量)
1.acquire()方法时,会消费一个许可证。如果没有许可证了,会阻塞起来
2.release()方法时,会添加一个许可证
又是小华,他们昨天晚上happy 之后,感觉身体太虚了,就相约去篮球场比赛投篮,只有一个球,所以他们在一个人投篮的时候要进行等待,一个人投完之后另一个人才能投
public static void main(String args[]){
//凭证数量为1
Semaphore semaphore=new Semaphore(1);
System.out.println("投篮比赛开始了。。。");
//启用3个线程
for(int i=1;i<=3;i++){
int finalI=i;
new Thread(()->{
String name="";
try{
if(finalI==1){
name="小华";
}else if(finalI==2){
name="小杰";
}else{
name="小虎";
}
System.out.println("轮到"+name+"投篮");
//当调用acquire()方法时,会消费一个许可证。如果没有许可证了,会阻塞起来。一个人投篮的时候,其他人只能看着
semaphore.acquire();
// 投篮花费的时间
Thread.sleep(1000);
//当调用release()方法时,会添加一个许可证。就是下一个人可以继续投篮了
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
}).start();
}
}
image.png
1.CountDownLatch(闭锁) 强调的是等待 1个等多个或者多个等一个
2.CyclicBarrier(栅栏) 强调的是状态 在某个状态下等待
3.Semaphore(信号量) 强调的是凭证,有凭证的为所欲为,没有的只能等待,要消费凭证
网友评论