常用辅助类
794字约3分钟
2024-08-08
CountDownLatch(减法计数器)
jdk 文档介绍
允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
A CountDownLatch
用给定的计数初始化。 await
方法阻塞,直到由于 countDown()
方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的 await
调用立即返回。 这是一个一次性的现象 - 计数无法重置。 如果您需要重置计数的版本,请考虑使用 CyclicBarrier
栗子
public static void main(String[] args) throws InterruptedException {
// 总数为 10
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " >> " + "do");
// 数量减 1
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
// 等待计数器归零,再往下执行
countDownLatch.await();
System.out.println("======end======");
}
原理
countDownLatch.countDown();
,数量减1
countDownLatch.await();
,等待计数器归零,再往下执行
每次有线程调用 countDown()
数量减 1
,当计数器变为 0
,countDownLatch.await();
就会被唤醒,继续执行
CyclicBarrier(加法计数器)
jdk 文档介绍
允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用
A CyclicBarrier
支持一个可选的 Runnable
命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前。 在任何一方继续进行之前,此屏障操作对更新共享状态很有用
栗子
public CyclicBarrier(int parties) {
this(parties, null);
}
// 到达指定数量后执行 Runnable 线程
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
/**
* 集齐七颗龙珠
* @param args
*/
public static void main(String[] args) {
// 召唤神龙的线程
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("召唤神龙");
});
for (int i = 1; i <= 7; i++) {
final 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();
}
}
Semaphore
Semaphore
:信号量
jdk 文档介绍
一个计数信号量。 在概念上,信号量维持一组许可证
如果有必要,每个 acquire()
都会阻塞,直到许可证可用,然后才能使用它
每个 release()
添加许可证,潜在地释放阻塞获取方。 但是,没有使用实际的许可证对象
Semaphore
只保留可用数量的计数,并相应地执行
栗子
public static void main(String[] args) {
// 有参构造,线程数量,限流(模拟抢车位,3 个车位)
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
try {
// acquire() 得到
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 抢到车位");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + " 离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
原理
semaphore.acquire();
获得,如果已经满了,等待,等待被释放为止semaphore.release();
释放,会将当前信号量释放1
,然后唤醒等待的线程
作用:多个共享资源互斥使用,并发限流,控制最大的线程数