1. CountDownLatch: 减法计数器
public class CountDownLatch extends Object 允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
A CountDownLatch
用给定的计数初始化。 await
方法阻塞,直到由于countDown()
方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await
调用立即返回。 这是一个一次性的现象 - 计数无法重置。 如果您需要重置计数的版本,请考虑使用CyclicBarrier
。
import java.util.concurrent.CountDownLatch;
class test1{
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" go out");
// 数量-1
countDownLatch.countDown();
},String.valueOf(i)).start();
}
// 等待计数器归零,然后再向下执行,如果不为0,就会等待!
countDownLatch.await();
System.out.println("close!");
}
}
countDownLatch.countDown(); // 数量-1
countDownLatch.await(); // 等待计数器归零,然后再向下执行
每次有线程调用 countDown() 数量-1,假设计数器变为0, countDownLatch.await() 就会被唤醒,继续执行!
2. CyclicBarrier: 加法计数器
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class test1{
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5,()->{
System.out.println("集五福成功!");
});
for (int i = 0; i < 5; i++) {
int temp = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"集到"+ temp +"个福!");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
// 结果:
0集到0个福!
3集到3个福!
2集到2个福!
1集到1个福!
4集到4个福!
集五福成功!
3. Semaphore: 信号量
public class Semaphore extends Object implements Serializable
一个计数信号量。 在概念上,信号量维持一组许可证。 如果有必要,每个acquire()
都会阻塞,直到许可证可用,然后才能使用它。 每个release()
添加许可证,潜在地释放阻塞获取方。 但是,没有使用实际的许可证对象; Semaphore
只保留可用数量的计数,并相应地执行。信号量通常用于限制线程数,而不是访问某些(物理或逻辑)资源。 例如,使用信号量来控制对一个项目池的访问!
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
class test1{
public static void main(String[] args) throws InterruptedException {
// 线程数量:停车位(一共3个车位,但是有5台车在抢!)! 可以帮助限流
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 5; i++) {
int temp = i;
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"抢到车位!");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
// 输出结果:
0抢到车位!
2抢到车位!
1抢到车位!
1离开车位!
2离开车位!
0离开车位!
4抢到车位!
3抢到车位!
4离开车位!
3离开车位!
semaphore.acquire(): 获得,假设如果已经满了,等待,等待被释放为止!
semaphore.release(): 释放,会将当前的信号量释放 + 1,然后唤醒等待的线程!
作用: 多个共享资源互斥的使用!并发限流,控制最大的线程数!