JUC 中三个超好用的辅助类
CountDownLatch
简介
CountDownLatch 是基于计数器的原理实现的, 它内部维护了一个整型的计数器。创建 CountDownLatch 对象时, 需要指定一个初始计数值, 该计数值表示需要等待的线程数量,使用其 await() 方法让其等待。每当一个线程完成了其任务, 可以调用 CountDownLatch 的 countDown() 方法, 计数器的值就会减一。当计数器的值变成 0 时, 等待的线程就会被唤醒, 继续执行它们的任务。
使用示例
public static void mian() throw InterruptedException{
//创建倒计时门闩对象
CountDownLatch latch = new CountDownLatch(5);
for(int i = 1 ; i <= 5 ; i++){
new Thread(()->{
try {
//模拟耗时操作
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println( i + "号线程执行完毕。");
//计数器减一
latch.countDown();
} , i + "");
}
//主线程等待其他五个线程执行完后才继续执行
downLatch.await();
//await() 的重载方法,当计数器计数为0或者等待时间到达 5 秒,主线程会被唤醒
//downLatch.await( 5 , TimeUnit.SECONDS );
System.out.println( "其他线程全部执行完毕,主线程继续运行。");
}
CyclicBarrier
简介
CyclicBarrier 可以让一组线程互相等待,直到所有线程都到达某个公共屏障点(Barrier point)。它是一个循环栅栏,因为线程可以在屏障点再次达到后重新进行等待。CyclicBarrier 的使用需要指定两个参数:参与的线程数和屏障触发时的处理程序。当指定数量的线程到达屏障点时,所有线程都会被唤醒,并且可以执行一些共享的操作。在 CyclicBarrier 中,线程在等待时会释放所占用的资源,因此它适用于在多线程环境下同步多个线程完成任务的情况。它也常用于实现并行计算和并发测试的场景。同时,CyclicBarrier 是可以重复使用的,只需要调用其 reset() 方法,便可将屏障恢复至初始状态。
使用示例
public static void main(String[] args) {
// 创建一个CyclicBarrier,指定参与的线程数和屏障触发时的处理程序
CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("所有线程都已到达屏障点,开始执行任务...");
// 在这里执行需要所有线程共同完成的任务
}
});
// 创建3个线程,分别执行不同的任务
Thread thread1 = new Thread(()->{
try {
//模拟耗时操作
Thread.sleep(1000);
//线程到达屏障点,等待其他线程
System.out.println( "1号线程到达屏障点。");
barrier.await();
//await() 的重载方法,当所有线程到达屏障点或者等待时间到达 5 秒,线程会被唤醒
//barrier.await( 5 , TimeUnit.SECONDS);
}catch (InterruptedException e){
e.printStackTrace();
}
}, "Thread-1");
Thread thread2 = new Thread(()->{
try {
Thread.sleep(1000);
System.out.println( "2号线程到达屏障点。");
barrier.await();
}catch (InterruptedException e){
e.printStackTrace();
}
}, "Thread-2");
Thread thread3 = new Thread(()->{
try {
Thread.sleep(1000);
System.out.println( "3号线程到达屏障点。");
barrier.await();
}catch (InterruptedException e){
e.printStackTrace();
}
}, "Thread-3");
// 启动线程
thread1.start();
thread2.start();
thread3.start();
//将屏障回复至初始状态,之后便可以再次使用
//barrier.reset()
}
Semaphore
简介
Semaphore 用于控制或限制对资源的访问。它是一个计数信号量,可以用来保护一段代码或共享资源,确保同时只有一个线程可以访问它,就类似抢车位。Semaphore 的使用需要创建一个 Semaphore 对象,并使用它的 acquire() 和 release() 方法来控制资源的访问。当一个线程需要访问资源时,它会调用 acquire() 方法来获取一个许可。如果许可可用,线程将获取许可并继续执行。如果许可不可用,线程将被阻塞,直到有可用的许可。当线程完成对资源的访问后,它会调用 release() 方法来释放许可,以便其他线程可以获取许可并访问资源。
使用示例
public static void main(String[] args) {
// 创建一个初始许可数为2的Semaphore,代表有两个车位
Semaphore semaphore = new Semaphore(2);
//创建4个线程,代表4辆汽车
for(int i = 1; i <= 4;i++){
Thread thread = new Thread(() -> {
try {
// 获取一个许可,代表抢到车位
semaphore.acquire();
System.out.println(i + "号汽车抢到车位");
// 模拟对资源的访问,代表停车
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
// 释放许可,代表离开车位
semaphore.release();
System.out.println(i + "号汽车离开车位");
}
}).start();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南