定时任务Spring(JAVA)
1.介绍
后续更新
2.使用
说明:pool-size="1"不配置的话,定时任务也是默认为单线程的
2.1 1个线程池1个线程
下面启动一个定时任务,线程池里只有一个线程,启动10秒后,每个5秒钟执行一次,定时任务里用sleep模拟执行时间,里面一个正常流程要消耗15秒钟
task.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<context:component-scan base-package="com.zy.common.task"/>
<task:scheduler id="threadPoolName_task" pool-size="1"/>
<task:scheduled-tasks scheduler="threadPoolName_task">
<task:scheduled ref="supplementRecordTask" method="pushVehicleData" cron="10/5 * * * * ?"/>
</task:scheduled-tasks>
</beans>
SupplementRecordTask
@Service("supplementRecordTask")
public class SupplementRecordTask {
private final ReentrantLock lock = new ReentrantLock();
private AtomicInteger num = new AtomicInteger(0);
public void pushVehicleData() {
int andIncrement = num.getAndIncrement();
LogUtils.logInfo("当前线程开始进入【"+andIncrement+"】=="+Thread.currentThread().getName() + "当前实体类:" + this.toString());
try {
lock.lock();
Thread.sleep(15000);
LogUtils.logInfo("当前线程开始结束【"+andIncrement+"】=="+Thread.currentThread().getName() + "当前实体类:" + this.toString());
}catch (Exception e){
System.out.println("e = " + e);
}finally {
lock.unlock();
}
}
}
结果:
由上图可知:
1.Spring生成的实例,默认是单例的
2.线程池配置一个线程,task:scheduled任务只有一个supplementRecordTask,那么每次该任务执行,都会是相同线程去执行
3.同一个scheduled任务执行时,若上一个任务没有执行完,会影响下一个任务的执行,必须等上一个任务执行完后,下一个任务才能开始执行,所以,这里lock其实可以不用加,不过安全起见,加上也没啥关系
2.1 1个线程池多个线程
这里修改线程数量,10秒后,每隔3秒执行一次,其他同上
<context:component-scan base-package="com.common.task"/>
<task:scheduler id="threadPoolName_task" pool-size="4"/>
<task:scheduled-tasks scheduler="threadPoolName_task">
<task:scheduled ref="supplementRecordTask" method="pushVehicleData" cron="10/3 * * * * ?"/>
</task:scheduled-tasks>
结果:
说明:
1.可以看出,本次线程池创建了4个线程来接收scheduled任务,而这次的scheduled只有一个,所以,可以从中选中一个线程来执行这个scheduled任务
2.同样的,虽然有多个线程,但是并不是异步执行的(这里把lock注销执行也是一样的结果),说明同一个scheduled是相互影响的
3.我们可以多增加如下配置,创建多个任务scheduled来执行,互不干扰
<task:scheduled-tasks scheduler="threadPoolName_task">
<task:scheduled ref="supplementRecordTask" method="pushVehicleData" cron="10/3 * * * * ?"/>
<task:scheduled ref="supplementRecordTask2" method="pushVehicleData" cron="10/3 * * * * ?"/>
</task:scheduled-tasks>
参考
spring定时任务-配置及解决并发问题
Spring定时任务并行(异步)处理
Spring 配置quartz定时任务及时间设置
Spring Framework----定时任务的执行和调度
Spring配置异步任务处理