5.Callable和计数器辅助类等
Callable
- 有返回值
- 可以抛出异常
- 方法不同:call
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
*Thread只能启动Runnable
* FutureTask实现了Runnable
* 而FutureTask构造方法可以传入Callable
* */
MyThread myThread = new MyThread();
FutureTask task = new FutureTask(myThread);
new Thread(task,"a").start();
new Thread(task,"b").start();//结果会被缓存,效率高
//get方法可能会产生阻塞,可以放到最后或者使用异步通信来处理
String s = (String) task.get();
System.out.println(s);
}
}
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("call()");
return "hello";
}
}
总结:1.缓存 2.结果需要等待,会阻塞
常用辅助类
CountDownLatch
//减法计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//总数6
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" go out");
countDownLatch.countDown();//数量-1
},String.valueOf(i)).start();
}
countDownLatch.await();//计数器归零,然后再往下执行
System.out.println("close door");
}
}
总结:
countDown();//数量-1
await();//等待计数器归零,然后再向下执行
每次线程调用countDown()数量-1,假设计数器变为0,.awit()就会被唤醒,继续执行
CyclicBarrier
//加法计数器
public class CyclicBarrierDemo {
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();
}
}).start();
}
}
}
Semaphore
信号量
原理:
-
semaphore.acquire();获得,假设如果已经满了,等待,等待被释放为止!
-
semaphour.release();释放,会将当前的信号量释放+1,然后唤醒等待的线程!
作用:
- 多个共享资源 互斥的使用!
- 并发限流,控制最大的线程数
/*
*Semaphore:信号量,相当于通行证,限流!
*acquire();得到
*release();释放
* */
public class SemaphoreDemo {
public static void main(String[] args) {
//线程数据量:3个停车位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
semaphore.acquire();//得到车位
System.out.println(Thread.currentThread().getName() + "抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "离开车位");
semaphore.release();//释放车位
} catch (InterruptedException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY