欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 定时任务总结一

程序员文章站 2022-04-04 16:46:50
...

 Java定时任务总结
 
 一.从技术上分类大概分为以下三种方式:
 
 1.Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务;
   说明:
    java.util.Timer定时器,实际上是个线程,定时执行TimerTask类
    一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。
 
 2.Java可以实现Runnable接口,这里不讲解,以后陆续补充;
   
 
 3.Spring3.0以后自带的task,可以看做一个轻量级的Quartz,它的实现方式如下:
   (1).Spring3.0 自带的作业调度(quartz)的两种业务处理方式
        a.org.springframework.scheduling.quartz.JobDetailFactoryBean
        b.org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
        说明:Spring通过JobDetailBean/JobDetailFactoryBean,MethodInvokingJobDetailBean/MethodInvokingJobDetailFactoryBean实现Job的定义。
     后者更加实用,只需指定要运行的类,和该类中要运行的方法即可,Spring将自动生成符合Quartz要求的JobDetail
    
   (2).Spring3.0 自带的作业调度(quartz)的两种触发方式:
         a. org.springframework.scheduling.quartz.SimpleTriggerBean  触发器  每隔多长时间运行一次 比如:每隔10分钟运行一次
         b. org.springframework.scheduling.quartz.CronTriggerBean    调度器  每到指定时间则触发一次  比如:每天12:00运行一次
  
   (3).配置调度任务,开启调度
       org.springframework.scheduling.quartz.SchedulerFactoryBean
      
二.具体操作实现:

1.java.util.Timer :
    一些基本方法的说明:
    Timer timer = new Timer(true);
 // true 说明这个timer以daemon方式运行(优先级低,
 // 程序结束timer也自动结束),注意,javax.swing
 // 包中也有一个Timer类,如果import中用到swing包,
 // 要注意名字的冲突。

 TimerTask task = new TimerTask() {
  public void run() {
   // 每次需要执行的代码放到这里面。
  }
 };

 // 以下是几种调度task的方法:

 //timer.schedule(task, time);
 // time为Date类型:在指定时间频度执行一次。

 //timer.schedule(task, firstTime, period);
 // firstTime为Date类型,period为long
 // 从firstTime时刻开始,每隔period毫秒执行一次。

 //timer.schedule(task, delay);
 // delay 为long类型:从现在起过delay毫秒执行一次

 //timer.schedule(task, delay, period);
 // delay为long,period为long:从现在起过delay毫秒以后,每隔period
 // 毫秒执行一次。

 

package com.TimerWay.Timer;

import java.util.TimerTask;

public class TimerTaskJunit extends TimerTask {

	@Override
	public void run() {
		System.out.println("TimerTask1=========");
	}

}

 

package com.TimerWay.Timer;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


public class Test {
	
	/**
	 * 从现在起过1000毫秒以后,每隔2000毫秒,执行一次TimerTaskJunit的Run方法
	 */
	public void test1(){
		Timer timer = new Timer();  
		timer.schedule(new TimerTaskJunit(), 1000, 2000);  
	}
	
	/**
	 * 每天中午11:00:00 执行定时任务,如果当前时间超过了11点,就明天执行11点执行任务
	 */
	public void test2(){
		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long period = 1000 * 60 * 24;//间隔执行时间  24分钟
		Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Date now = new Date();
                System.out.println(sdf.format(now)+"\t helloworld");
            }
        },DateUtil.timeInMillis(), period);
	}
	
	public static void main(String[] args) {
		Test t = new Test();
		t.test1();
		//t.test2();
		
	}
}

 2.Spring3.0 自带的Quartz

    a.org.springframework.scheduling.quartz.JobDetailFactoryBean

   

<bean name="productDetail" class="com.TimerWay.quartz2.ProductDetail"/>


<bean name="runJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="com.TimerWay.quartz2.RunJob" />
		
		<!-- 属性注入  任务执行时 ,将属性注入到 jobClass对应Value类的属性 -->
		<property name="jobDataAsMap">
			<map>
				<entry key="productDetail" value-ref="productDetail" />
			</map>
		</property>
	</bean>



<!-- Simple Trigger, run every 5 seconds first trigger -->
	<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
		<!-- 任务 -->
		<property name="jobDetail" ref="runJob" />
		<!-- 频度  每10分钟做一次任务 -->
		<property name="repeatInterval" value="600000" />
		<!-- 待延迟之后,开始工作 -->
		<property name="startDelay" value="1000" />
	</bean>


<!-- 配置调度,启动调度任务 -->
	<bean id="schdulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobDetails">
			<list>
				<ref bean="runMeJob" />
			</list>
		</property>
		<property name="triggers">
			<list>
				<ref bean="simpleTrigger" />
			</list>
		</property>
		<!-- 
		<property name="triggers">
			<list>
				<ref bean="cronTrigger" />
			</list>
		</property>
		 -->
		
	</bean>

 

package com.TimerWay.quartz2;

import org.apache.log4j.Logger;


/**
 * 更新商城发货单的状态
 * @author daizhao
 *
 */
public class ProductDetail {
	
	private final static Logger log = Logger.getLogger(ProductDetail.class);
	
	public void product(){
		
		log.info("生产。。。。");
	}
}

 

说明:在这里我用的触发器是org.springframework.scheduling.quartz.SimpleTriggerFactoryBean,也可用

org.springframework.scheduling.quartz.CronTriggerFactoryBean,下面的例子,采用。

   b.org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean

  

<bean name="productDetail" class="com.TimerWay.quartz2.ProductDetail"/>
<!-- 会自动的生成JobDetailFactoryBean -->
	<bean id="runMeJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactor yBean">
		<!-- 要执行业务的Bean  --> 
		<property name="targetObject" ref="productDetail" /> 
		<!-- 执行业务的方法  -->
		<property name="targetMethod" value="product" /> 
	</bean> 

<!--Cron Trigger, run every 5 seconds  second trigger  类似Unix中的Crontab的脚步机制-->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<!-- 任务 -->
	<property name="jobDetail" ref="runJob" />
	<!-- 频度 -->
	<property name="cronExpression" value="0/5 * * * * ?" />
	</bean>

<!-- 配置调度,启动调度任务 -->
	<bean id="schdulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobDetails">
			<list>
				<ref bean="runMeJob" />
			</list>
		</property>
		<property name="triggers">
			<list>
				<ref bean="cronTrigger" />
			</list>
		</property>		
	</bean>

 说明:我解释一些,为什么我用这个JobDetailBean/JobDetailFactoryBean,MethodInvokingJobDetailBean/MethodInvokingJobDetailFactoryBean实现Job的定义,因为,有的时候,开发时,会遇到Spring自带的Quartz和Quartz包冲突的问题,异常如下:

 

Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.JobDetailBean has interface org.quartz.JobDetail as super class
 
Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class
 
Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.SimpleTrigger has interface org.quartz.SimpleTrigger as super class

所以,解决方式如下:

 

1.降低Quartz版本,降到1.X去。
2.升级Spring版本到3.1+,根据Spring的建议,将原来的**TriggerBean替换成**TriggerFactoryBean,例如CronTriggerBean 就可以替换成 CronTriggerFactoryBean,  SimpleTriggerBean可以替换成SimpleTriggerFactoryBean,JobDetailBean可以替换成JobDetailFactoryBean
替换之后问题解决。

我后续,还会补充,Spring的注解定时任务和JavaRunnable定时任务,今天先到这里