多线程注解@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

posted @   码农公子的幸福生活  阅读(2152)  评论(0编辑  收藏  举报
编辑推荐:
· 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代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示