多线程注解@Async的使用
多线程注解@Async的使用
1.在启动类Application中添加注解@EnableAsync
2.启动类需要实现AsyncConfigurer
3.配置线程池
//配置线程池
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
/** 核心线程数(默认线程数) */
taskExecutor.setCorePoolSize(25);
/** 最大线程数 */
taskExecutor.setMaxPoolSize(50);
/** 缓冲队列大小 */
taskExecutor.setQueueCapacity(25);
/** 允许线程空闲时间(单位:默认为秒) */
taskExecutor.setKeepAliveSeconds(300);
// 线程池对拒绝任务的处理策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
实际项目中最大允许的线程数为75个,核心+队列+max(50-核心)
4.在需要异步的方法中加入@Async,此时需要考虑线程同步问题,可使用CountDownLatch
//对每个数据源开启一个线程
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(map.size());
for (Integer dbids : map.keySet()) {
List<Integer> integerList = map.get(dbids);
//异步处理
mentService.dealData(countDownLatch, integerList, list);
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("查询信息花费:" + (end - start));
@Async
public void dealData(CountDownLatch countDownLatch, List<Integer> integerList,List<Map<String, Object>> list) {
logger.info("当前线程名字" + Thread.currentThread().getName());
try {
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
CountDownLatch的用法:
CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,构造CountDownLatch的时候需要传入一个整数n,在这个整数“倒数”到0之前,主线程需要等待在门口,而这个“倒数”过程则是由各个执行线程驱动的,每个线程执行完一个任务“倒数”一次。总结来说,CountDownLatch的作用就是等待其他的线程都执行完任务,必要时可以对各个任务的执行结果进行汇总,然后主线程才继续往下执行。
@Async注解的注意事项:
1.@SpringBootApplication启动类当中没有添加@EnableAsync注解。
2.方法是公有的
3.异步代码,需要放在外部单独的类中,不能在同一个类中调用同一个方法,否则会是同步处理
( 据说这是一个“常识”,外部方法才会被Spring拦截器拦截到额),没有走Spring的代理类。因为@Transactional和@Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。那么注解失效的原因就很明显了,有可能因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器管理。也可以通过自己注入自己的方式)
4.异步方法使用注解@Async的返回值只能为void或者Future
5.debug断点调试情况下是看不出效果的,可通过在调用后打印时间在异步方法中打印时间的方式查看,如果要debug程序代码,可以把注解注释掉
线程的运行说明:
execute(Runable)方法执行过程
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数
具体信息参照https://www.cnblogs.com/redcool/p/6426173.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南