这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」
工具类
CountDownLatch
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
// 减法计数器 ,new 对象的时候指定总数 5
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(()->{
// 每当执行完一次任务,将其数量-1
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+":"+countDownLatch.getCount());
},String.valueOf(i)).start();
}
// 当数量变为0时,await()就会被唤醒,后面的代码继续执行,如果没有变成0,就不会执行
countDownLatch.await();
System.out.println("111");
复制代码
这里发现但count没有变为0,循环结束了,到await的时候没有被唤醒,就无法输出111
CyclicBarrier
加法计数器。当增加的数量达到指定的数量,就会执行里面的方法
// cyclicBarrier 的方法
CyclicBarrier cyclicBarrier = new CyclicBarrier(5,()->{
System.out.println("当cyclicBarrier达到5个,就会执行输出该语句(执行操作)");
});
for (int i = 0; i < 4; i++) {
new Thread(()->{
try {
// 给数量+1
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+":"+cyclicBarrier.getNumberWaiting());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
复制代码
CountDownLathc和CyclicBarrier的区别
1.CountDownLathc是一次性的,当达到条件执行完后就会停止
2.CyclicBarrier是可复用的
semaphore
相当于许可证,只有拿到许可证的人才能执行操作。操作完之后释放许可证给其他人。
// new时定义了该实例拥有几个sunc锁
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
// 拿到1个锁
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
复制代码
// 限定3个锁
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
try {
// 这个线程得到1个锁,许可证数量-1 ,如果许可证数量为0,等待其他线程释放锁.
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"获得锁");
// 等待2秒后释放
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
// 释放锁,使许可证+1
semaphore.release();
System.out.println(Thread.currentThread().getName()+"释放锁");
}
}, String.valueOf(i)).start();
}
复制代码
并发限流,限制最大并发数