赞
踩
@Scheduled在spring中默认是使用一个线程的线程池执行调度任务的。
下面是我的测试代码:
1、pom文件配置
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>com.wsj.monitor</groupId>
- <artifactId>monitor</artifactId>
- <version>1.0-SNAPSHOT</version>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.7.RELEASE</version>
- </parent>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-quartz</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- </dependencies>
-
-
- </project>

启动类配置:
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.scheduling.annotation.EnableScheduling;
-
- @SpringBootApplication
- @EnableScheduling
- public class MonitorApp {
- public static void main(String[] args) {
- SpringApplication.run(MonitorApp.class,args);
- }
- }
测试job
- package com.tyyd.monitor.job;
-
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
-
- import java.util.concurrent.TimeUnit;
-
- @Component
- public class TestJob {
-
- @Scheduled(cron = "0/10 * * * * ?")
- public void testJob1() throws InterruptedException {
- System.out.println("执行了TestJob1,执行的线程名称是:"+Thread.currentThread().getName());
- //休眠20秒
- TimeUnit.SECONDS.sleep(20);
- }
-
- @Scheduled(cron = "0/5 * * * * ?")
- public void testJob2(){
- System.out.println("执行了TestJob2,执行的线程名称是:"+Thread.currentThread().getName());
- }
- }

执行结果,看到使用的都是同线程池的线程。
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob1,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob1,执行的线程名称是:pool-1-thread-1
线程池使用配置:
- package com.wsj.monitor.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.scheduling.annotation.SchedulingConfigurer;
- import org.springframework.scheduling.config.ScheduledTaskRegistrar;
-
- import java.util.concurrent.Executors;
-
- /***
- * @Scheduled 注解默认使用的是单线程,1个任务卡死。会产生连锁反应。
- * 配置任务线程池可以让同步任务并行执行调度
- * @Scheduled(cron="0 1***?")
- */
- @Configuration
- public class ScheduleConfig implements SchedulingConfigurer {
- @Override
- public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
- //设定一个启动10个线程的定时调度线程池
- taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
- }
- }

配置后执行结果
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-2
- 执行了TestJob1,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-2
- 执行了TestJob2,执行的线程名称是:pool-1-thread-4
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-5
- 执行了TestJob2,执行的线程名称是:pool-1-thread-6
- 执行了TestJob1,执行的线程名称是:pool-1-thread-2
- 执行了TestJob2,执行的线程名称是:pool-1-thread-4
- 执行了TestJob2,执行的线程名称是:pool-1-thread-4
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
注意,spring 的quartz是可以使用异步的。再启动类上开启异步支持@EnableAsync 并在要异步的任务上加个@Async。
如果所有的任务都使用异步,线程池执行的话,可以不配置同步任务线程池。但是使用异步需要注意的是异步线程池的大小配置。异步的线程池默认是无上限的开启线程数的。
- @Component
- public class TestJob {
-
- @Async
- @Scheduled(cron = "0/3 * * * * ?")
- public void testJob1() throws InterruptedException {
- System.out.println("执行了TestJob1,执行的线程名称是:"+Thread.currentThread().getName());
- TimeUnit.SECONDS.sleep(20);
- }
-
- @Scheduled(cron = "0/5 * * * * ?")
- public void testJob2(){
- System.out.println("执行了TestJob2,执行的线程名称是:"+Thread.currentThread().getName());
- }
- }
执行结果:
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-1
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-2
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-2
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-4
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-5
- 执行了TestJob2,执行的线程名称是:pool-1-thread-3
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-6
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-7
- 执行了TestJob2,执行的线程名称是:pool-1-thread-2
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-8
- 执行了TestJob2,执行的线程名称是:pool-1-thread-8
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-9
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-10
因为异步线程池没做控制默认无上限肯定不行的。修改配置如下:
- package com.wsj.monitor.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.task.SimpleAsyncTaskExecutor;
- import org.springframework.scheduling.annotation.EnableAsync;
- import org.springframework.scheduling.annotation.SchedulingConfigurer;
- import org.springframework.scheduling.config.ScheduledTaskRegistrar;
-
- import java.util.concurrent.Executors;
-
- /***
- * @Scheduled 注解默认使用的是单线程,1个任务卡死。会产生连锁反应。
- * 配置任务线程池可以并行执行调度
- * @Async
- * @Scheduled(cron="0 1***?")
- * 可以在scheduled上加上异步注解 ,每个任务都是一个新的线程
- * 如果是异步,每卡住一个任务都会占用一个线程资源,直到线程池线程资源全部占用定时调度挂掉
- */
- @Configuration
- @EnableAsync
- public class ScheduleConfig implements SchedulingConfigurer {
- @Override
- public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
- //设定一个长度10的定时任务线程池
- taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
- }
-
- /**
- * 异步线程池设置
- * @return
- */
- @Bean
- SimpleAsyncTaskExecutor simpleAsyncTaskExecutor(){
- SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
- simpleAsyncTaskExecutor.setConcurrencyLimit(2);//设置最大并行数
- simpleAsyncTaskExecutor.setDaemon(true); //设置为守护线程
- return simpleAsyncTaskExecutor;
- }
- }

修改配置后,看到执行结果最大同时异步为2个结果如下:
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-2
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-2
- 执行了TestJob2,执行的线程名称是:pool-1-thread-4
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-5
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-3
- 执行了TestJob2,执行的线程名称是:pool-1-thread-6
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-4
- 执行了TestJob2,执行的线程名称是:pool-1-thread-1
- 执行了TestJob2,执行的线程名称是:pool-1-thread-8
- 执行了TestJob2,执行的线程名称是:pool-1-thread-8
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-5
- 执行了TestJob2,执行的线程名称是:pool-1-thread-8
- 执行了TestJob1,执行的线程名称是:SimpleAsyncTaskExecutor-6
- 执行了TestJob2,执行的线程名称是:pool-1-thread-8
- 执行了TestJob2,执行的线程名称是:pool-1-thread-5
- 执行了TestJob2,执行的线程名称是:pool-1-thread-5

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。