ExecutorService
ScheduledExecutorService
ThredPoolTaskExecutor
ThredPoolTaskScheduler
Spring Quartz
1. 分布式换环境下的定时任务问题
Schedule每隔一段时间做同样的事情,做的任务会重复
Quartz定时任务驱动的参数存到数据库里,通过排队加锁等这样的机制实现共享
2. JDK线程池
注意:main方法的线程如果不挂掉会一直等着它执行,但是juint方法中线程如果后面没有逻辑立马就结束了。解决方法启动之后等一下,让当前线程阻塞一会,但是sleep方法又经常抛异常,为了调起来方便把sleep封装一下
private void sleep(long m) {
try {
Thread.sleep(m);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2.1 普通线程池 ExecutorService
- 通过
newFixedThreadPool
工厂实例化普通线程池 - 实现一个
Runnable()
方法的匿名实现,任务为logger.debug("Hello ExecutorService");
submit
(执行)十次sleep
10000毫秒
2.2 定时任务线程池ScheduledExecutorService
- 通过
newScheduledThreadPool
工厂实例化定时任务线程池 - 实现一个
Runnable()
方法的匿名实现,任务为logger.debug("Hello ExecutorService");
- 调用
scheduledExecutorService
的方法scheduleAtFixedRate
,参数为:传入任务,延迟时间,时间间隔,数字单位:scheduledExecutorService.scheduleAtFixedRate(task, 10000, 1000, TimeUnit.MILLISECONDS);
sleep
10000毫秒
3. Spring线程池
3.1 配置文件 application.properties
3.1.1 普通线程池
core-size
:核心线程数量max-size
:自动扩容上限queue-capacity
:队列容量,最大容量也不够用时,放入队列进行缓冲
# TaskExecutionProperties
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=15
spring.task.execution.pool.queue-capacity=100
3.1.2 定时任务线程池
size
:线程数量
# TaskSchedulingProperties
spring.task.scheduling.pool.size=5
3.2 配置类 ThreadPoolConfig
@Configuration
@EnableScheduling
@EnableAsync
public class ThreadPoolConfig {
}
3.3 Spring普通线程池:ThreadPoolTaskExecutor
- 注入普通线程池
ThreadPoolTaskExecutor
- 实现一个
Runnable()
方法的匿名实现,任务为logger.debug("Hello ExecutorService");
submit
(执行)十次sleep
10000毫秒- 比JDK自带的线程池更灵活
3.4 Spring定时任务线程池:ThreadPoolTaskScheduler
- 注入定时任务线程池
ThreadPoolTaskScheduler
- 实现一个
Runnable()
方法的匿名实现,任务为logger.debug("Hello ExecutorService");
- 调用
taskScheduler.scheduleAtFixedRate
,线程任务,开始时间,时间间隔 sleep
10000毫秒
3.5 Spring普通线程池(简化)
3.5.1 在任一service下写入以下语句
如在AlphaService中
// 让该方法在多线程环境下,被异步的调用.
@Async
public void execute1() {
logger.debug("execute1");
}
3.5.2 ThreadPoolTests
@Autowired
private AlphaService alphaService;
// 5.Spring普通线程池(简化)
@Test
public void testThreadPoolTaskExecutorSimple() {
for (int i = 0; i < 10; i++) {
alphaService.execute1();
}
sleep(10000);
}
3.6 Spring定时任务线程池(简化)
3.6.1 在任一service下写入以下语句
如在AlphaService中
/*@Scheduled(initialDelay = 10000, fixedRate = 1000)*/
public void execute2() {
logger.debug("execute2");
}
3.6.2 ThreadPoolTests
// 6.Spring定时任务线程池(简化)
@Test
public void testThreadPoolTaskSchedulerSimple() {
sleep(30000);
}
4. Spring Quartz
4.1 pom.xml 导入包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
4.2 核心组件
- scheduler 接口:核心调度工具,所有任务由这一接口调用
- job:定义任务,重写execute方法
- JobDetail接口:配置描述
- Trigger接口:什么时候运行,以什么样的频率运行
启动后,配置信息存入数据库,只在第一次启用
4.3 导入数据库
- qrtz_job_details:job详情配置描述表
- qrtz_simple_triggers:触发器相关配置简述
- qrtz_jtriggers:触发器相关完整配置
- qrtz_scheduler:定时器状态
- qrtz_locks:定时器锁
4.4 AlphaJob
打印当前线程名字
public class AlphaJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println(Thread.currentThread().getName() + ": execute a quartz job.");
}
}
4.5 QuartzConfig
配置的作用事第一次被读取到数据库,后面就不用了
FactoryBean可简化Bean的实例化过程:
1. 通过FactoryBean封装Bean的实例化过程.
2. 将FactoryBean装配到Spring容器里.
3. 将FactoryBean注入给其他的Bean.
4. 该Bean得到的是FactoryBean所管理的对象实例.
- 配置JobDetail
- 实例化
JobDetailFactoryBean
- 声明管理的管理的是谁
.setJobClass
- 声明job任务的名字
.setName
- 声明任务属于的组
.setGroup
- 声明任务是否长久保存
.setDurability
- 声明任务是否可恢复
.setRequestsRecovery
- 实例化
// 配置JobDetail
@Bean
public JobDetailFactoryBean alphaJobDetail() {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(AlphaJob.class);
factoryBean.setName("alphaJob");
factoryBean.setGroup("alphaJobGroup");
factoryBean.setDurability(true);
factoryBean.setRequestsRecovery(true);
return factoryBean;
}
- 配置Trigger
- 实例化
SimpleTriggerFactoryBean
- 声明管理的管理的是谁
.setJobClass
- 声明job任务的名字
.setName
- 声明任务属于的组
.setGroup
- 声明任务执行的频率
.setRepeatInterval
- 声明Trigger的存储状态类型
.setJobDataMap
- 实例化
// 配置Trigger(SimpleTriggerFactoryBean, CronTriggerFactoryBean)
@Bean
public SimpleTriggerFactoryBean alphaTrigger(JobDetail alphaJobDetail) {
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(alphaJobDetail);
factoryBean.setName("alphaTrigger");
factoryBean.setGroup("alphaTriggerGroup");
factoryBean.setRepeatInterval(3000);
factoryBean.setJobDataMap(new JobDataMap());
return factoryBean;
}
4.6 Quartz底层线程池配置
# QuartzProperties
spring.quartz.job-store-type=jdbc #存储方式
spring.quartz.scheduler-name=communityScheduler #调度器名字
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO #调度器id自动生成
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX #存入数据库的类
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate #驱动
spring.quartz.properties.org.quartz.jobStore.isClustered=true #采用集群
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool #用哪个线程池
spring.quartz.properties.org.quartz.threadPool.threadCount=5 #线程池数量
4.7 写程序删除job:QuartzTests
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class QuartzTests {
@Autowired
private Scheduler scheduler;
@Test
public void testDeleteJob() {
try {
boolean result = scheduler.deleteJob(new JobKey("alphaJob", "alphaJobGroup"));
System.out.println(result);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}