JUC并发包:CountDownLatch、CyclicBarrier、Semaphore使用
1.CountDownLatch
让一些线程堵塞直到另一个线程完成一系列操作后才被唤醒。CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被堵塞,其他线程调用 countDown 方法会将计数减一(调用 countDown 方法的线程不会堵塞),当计数其值变为零时,因调用 await 方法被堵塞的线程会被唤醒,继续执行。
案例:
假设有这么一个场景,教室里有班长和其他6个人在教室上自习,怎么保证班长等其他6个人都走出教室在把教室门给关掉。
package com.juc.interview;
import java.util.concurrent.CountDownLatch;
/**
* @description: juc下的类学习
* @author: Mr.Li
* @create: 2019-09-29 21:25
**/
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + "离开了教室");
}, String.valueOf(i)).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("班长把门关上了...");
}
}
运行结果:
1离开了教室
2离开了教室
4离开了教室
5离开了教室
3离开了教室
6离开了教室
班长把门关上了...
Process finished with exit code 0
2.CyclicBarrier
字面意思是可循环(Cyclic)使用的屏障(Barrier)。他要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法。
案例:
我们假设有这么一个场景,每辆车只能坐4个人,当车满了,就发车。
package com.juc.interview;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @description: CyclicBarrier学习
* @author: Mr.Li
* @create: 2019-09-29 21:57
**/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, ()->{
System.out.println("车满了,开始发车");
});
for (int i = 1; i <= 8; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "成功上车");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
运行结果:
1成功上车
2成功上车
4成功上车
5成功上车
车满了,开始发车
7成功上车
3成功上车
8成功上车
6成功上车
车满了,开始发车
Process finished with exit code 0
3.Semaphore
信号量主要用于两个目的,一个是用于多个共享资源的互斥作用,另一个用于并发线程数的控制。
案例:
假设我们有 3 个停车位,6 辆车去抢
package com.juc.interview;
import java.util.concurrent.Semaphore;
/**
* @description: SemaphoreDemo学习
* @author: Mr.Li
* @create: 2019-09-29 22:07
**/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; 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();
}
}).start();
}
}
}
运行结果:
Thread-0抢到车位
Thread-2抢到车位
Thread-1抢到车位
Thread-2离开车位
Thread-0离开车位
Thread-1离开车位
Thread-4抢到车位
Thread-3抢到车位
Thread-5抢到车位
Thread-3离开车位
Thread-4离开车位
Thread-5离开车位
Process finished with exit code 0
每日一言:
人生就像射箭,而梦想就像箭靶子,如果你连箭靶子都找不到的话,那每天的拉弓就毫无意义