前言

我们创建一个定时任务实例

@Component
@EnableScheduling
@Slf4j
public class Schedule {
    
    @Scheduled(cron = "* * * * * ?")
    public void run() throws InterruptedException {
        System.out.println( DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        Thread.sleep(3000);
    }
}

当在方法体中加入Thread.sleep时,发现并未每秒打印,而是等待3秒后再打印,说明springboot自带的定时器是阻塞的,如何实现异步执行,有三种方法

方法一、使用线程池异步调用

1、创建线程池

1.1 创建容器

@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(1000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

1.2 读取配置文件

@ConfigurationProperties(prefix = "mall.thread")
@Data
public class ThreadPoolConfigProperties {

    private Integer coreSize;

    private Integer maxSize;

    private Integer keepAliveTime;


}

1.3 application.properties配置

mall.thread.core-size=20
mall.thread.max-size=200
mall.thread.keep-alive-time=10

1.4 在定时器中的run()方法调用异步

@Autowired
    private ThreadPoolExecutor executor;

    @Scheduled(cron = "* * * * * ?")
    public void run() throws InterruptedException {
        CompletableFuture.runAsync(()->{
            System.out.println( DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        }, executor);
        Thread.sleep(3000);
    }

方法二、使用Spring自带的配置

在 application.properties配置

spring.task.scheduling.pool.size=10

原代码不用改变

@Scheduled(cron = "* * * * * ?")
    public void run() throws InterruptedException {
        System.out.println( DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        Thread.sleep(3000);
    }

上述方法有问题,不太准确

方法三、使用异步注解

@EnableAsync 与 @Async

@EnableAsync
@Component
@EnableScheduling
@Slf4j
public class Schedule {
	@Async
    @Scheduled(cron = "* * * * * ?")
    public void run2() throws InterruptedException {
        System.out.println("run2==" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    }

}

在 application.properties配置

spring.task.execution.pool.core-size=20
spring.task.execution.pool.max-size=50

QQ群:722865146
分布式商城下载:https://gitee/charlinchenlin/wysmall

更多推荐

Springboot Schedule定时任务实现异步的三种方法