在原生java中,创建和启动线程的方式大致有以下几种:

  1. 继承Thread类,然后重写run方法
  2. 实现Runnable接口,并重写run方法
  3. 匿名内部类
 Thread thread = new Thread(new Runnable() {
     @Override
     public void run() {
         // 线程实现
     }
 });
 thread.start();
  1. lambda表达式
  new Thread(()->{
      // 线程实现
  }).start();

在springboot中,推荐使用线程池的方式来管理多线程。
首先,添加配置类:

@Configuration
@EnableAsync
public class ThreadPoolConfig {
    /**
     * 核心线程池大小50
      */
    private static final int CORE_POOL_SIZE = 10;

    /**
     * 最大可创建的线程数200
      */
    private static final int MAX_POOL_SIZE = 10;

    /**
     * 队列最大长度1000
      */
    private static final int QUEUE_CAPACITY = 10;

    /**
     * 线程池维护线程所允许的空闲时间300
      */
    private static final int KEEP_ALIVE_SECONDS = 300;

    /**
     * 异步执行方法线程池
     *
     * @return
     */
    @Bean(name = "asyncExecutor")
    public ThreadPoolTaskExecutor eventExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

这里需要特别注意类上的两个注解,@Configuration声明当前类为一个配置类,@EnableAsync开启对异步任务的支持。
接着,在service实现方法上添加注解@Async("asyncExecutor"),这里的asyncExecutor对应config里面的执行器名称。

关于添加了@Async注解,但是没事异步执行线程方法的情况貌似还有点多,主要是大家没有按照规范来使用,或者没有注意到一些细节点。
下面总结一些常见的易错点:

  1. 添加@EnableAsync注解,开启异步任务支持
  2. 异步方法必须是public且void(或Future)
  3. 异步方法所在的类必须添加@Component或者其它注解,加入到容器中
  4. 调用者与被调用者在同一个类中,且直接调用。这种情况和spring的事务一样,都是通过aop实现的,所以一定要用代理类的方法才能够实现。如果调用者和被调用者都在同一个类中,使用spring上下文,获取到对应的代理类再执行异步方法。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐