CountDownLatch
public class CountDownDemo {
/**
* countdown倒计时的意思;允许一个或者多个线程被阻塞,等待其他线程执行完在被唤醒,有点类似join
* 应用场景:可以用来控制并发量,在某个条件之后实现秒杀
* @param args
*/
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3);
//3-1
new Thread(countDownLatch::countDown).start();
//2-1
new Thread(countDownLatch::countDown).start();
//1-1=0
new Thread(countDownLatch::countDown).start();
countDownLatch.await();
//等待countdown次数被减完,再去唤醒主线程
System.out.println("主线程执行完~");
}
}
下面简单展示一下秒杀操作
public class MyCountDownLatch implements Runnable {
static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new MyCountDownLatch(), "myCountDownThread" + i).start();
}
System.out.println("2秒后执行秒杀操作吧!"+ System.currentTimeMillis());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
@Override
public void run() {
try {
countDownLatch.await();
System.out.println("wait for countDownLatch: " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// print result
2秒后执行秒杀操作吧!1597648975555
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
wait for countDownLatch: 1597648977556
...
// 大概看了90%的误差在1ms
那光会用还远远不够啊,接下来我们到胃深入一下看看
countDownLatch先到这里
Semaphore
顾名思义就是我们停车场的信号灯,可以控制同时可以访问的线程数,类似限流的作用
public class MySemaphore {
static Semaphore semaphore = new Semaphore(5);
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(new Car(i, semaphore)).start();
}
}
static class Car implements Runnable{
private Integer carId;
private Semaphore carSemaphore;
public Car(Integer carId, Semaphore semaphore) {
this.carId = carId;
this.carSemaphore = semaphore;
}
@Override
public void run() {
try {
carSemaphore.acquire();
System.out.println("第"+carId+"辆车进来了");
TimeUnit.SECONDS.sleep(4);
System.out.println("第"+carId+"辆车走了");
carSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// print result
第0辆车进来了
第3辆车进来了
第2辆车进来了
第1辆车进来了
第5辆车进来了
第5辆车走了
第3辆车走了
第2辆车走了
第4辆车进来了
第7辆车进来了
第0辆车走了
第1辆车走了
第8辆车进来了
第6辆车进来了
第11辆车进来了
// 停车场最多停5辆车
第11辆车走了
第4辆车走了
第9辆车进来了
第7辆车走了
第6辆车走了
第13辆车进来了
第8辆车走了
第14辆车进来了
第12辆车进来了
第10辆车进来了
第14辆车走了
第9辆车走了
第10辆车走了
第12辆车走了
第13辆车走了
用力深入进去发现又有AQS不愧是并发的核心啊
CyclicBarrier
表面上看起来是一个可循坏使用的屏障,线程到达屏障会被阻塞直到,一组线程全部到达屏障时候才会继续工作
public class MyCyclicBarrier implements Runnable{
@Override
public void run() {
System.out.println("最后进行筛选处理");
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, new MyCyclicBarrier());
new TestThread("my girl1", cyclicBarrier).start();
new TestThread("my girl2", cyclicBarrier).start();
new TestThread("my girl3", cyclicBarrier).start();
new TestThread("my girl4", cyclicBarrier).start();
}
static class TestThread extends Thread{
private String name;
private CyclicBarrier cb;
public TestThread(String name, CyclicBarrier cb) {
this.name = name;
this.cb = cb;
}
@Override
public void run() {
try {
System.out.println(name);
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
// print result
my girl1
my girl4
my girl3
my girl2
最后进行筛选处理