Springboot集成定时器和多线程异步处理操作

需求:用@schedule标签进行定时处理逻辑,由于业务处理速度慢,需要每次执行逻辑放在不同的线程里异步执行

springboot集成多线程异步,直接上配置:

/**
 * 线程池异步配置
 */
 
@Configuration
@EnableAsync
public class ThreadExecutorConfig
    implements AsyncConfigurer { 
 
  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // 设置核心线程数
    executor.setCorePoolSize(5);
    // 设置最大线程数
    executor.setMaxPoolSize(7);
    // 设置队列容量
    executor.setQueueCapacity(20);
    // 设置线程活跃时间(秒)
    executor.setKeepAliveSeconds(60);
    // 设置默认线程名称
    executor.setThreadNamePrefix("PASCAL-");
    // 设置拒绝策略
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    // 等待所有任务结束后再关闭线程池
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.initialize();
    return executor;
  }
 
  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new MyAsyncUncaughtExceptionHandler();
  }
}

下面的是对多线程异步的时候报出的异常处理方法,可以自定义一个处理多线程异常类来实现自身的业务逻辑.

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 
import java.lang.reflect.Method;
 
public class MyAsyncUncaughtExceptionHandler implements
    AsyncUncaughtExceptionHandler {
  @Override
  public void handleUncaughtException(Throwable ex,
                    Method method, Object... params) { 
      // handle exception
  }
}

启动类上要记得添加异步和开启定时器的标签

@SpringBootApplication
@EnableScheduling
@Async
public class MultithreadingApplication {
 
  public static void main(String[] args) {
    SpringApplication.run(MultithreadingApplication.class, args);
  } 
}

业务逻辑方法:

  @Async
  @Scheduled(initialDelay=1000,fixedDelay = 5000)
  public void test(){
    SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
    try {
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
      Thread.sleep(10000);
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

对于@Schedule注解的使用方法:

点进去可以看到有几个可选参数:

fixedDelay:控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次

fixedRate:是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。

initialDelay:如: @Scheduled(initialDelay = 10000,fixedRate = 15000

这个定时器就是在上一个的基础上加了一个initialDelay = 10000 意思就是在容器启动后,延迟10秒后再执行一次定时器,以后每15秒再执行一次该定时器.

cron表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。

这里可以根据自身的业务需求,看到底选择哪一个更适合,这里cron表达式就不再多言,可以结合自身应用场景来定

这样,需求就实现了

测试结果:

20-07-07 11:12:40.436 INFO 32360 --- [      main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started>
/**
 * 配置多个schedule的线程配置
 */
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer{
  /*
   * 并行任务
   */
  public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
  {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setThreadNamePrefix("Schedule-Task-");
    taskScheduler.setPoolSize(5);
    taskScheduler.setAwaitTerminationSeconds(60);
    taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
    taskScheduler.initialize();
    taskRegistrar.setTaskScheduler(taskScheduler);
  }
}

业务如下:

  @Scheduled(cron = "*/5 * * * * ?")
  public void test1(){
    SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
    try {
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
      Thread.sleep(10000);
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
 
  @Scheduled(cron = "*/5 * * * * ?")
  public void test2(){
    SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
    try {
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
      Thread.sleep(10000);
      logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

Springboot集成定时器和多线程异步处理操作

扫一扫手机访问