定时任务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();
        }
    }
}

结果:
定时任务Spring(JAVA)
由上图可知:
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>

结果:
定时任务Spring(JAVA)
说明:
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配置异步任务处理