1. 程式人生 > >Spring的業務層和Web層-----------任務排程

Spring的業務層和Web層-----------任務排程

任務排程

  quartz框架

  quartz框架實現了Spring的任務排程,使用者可以隨意的定義觸發器排程時間表,並將觸發器和任務進行對映。quartz通過排程器、觸發器和任務實現任務排程。

  Job:主要用來設計任務實現的邏輯,並且只有一個方法execute。

  JobDetail:主要用來通過newInstance()方法建立Job例項,該角色主要通過一些靜態資訊來描述Job的名稱等資訊。

  Triger:作為任務的觸發器,有兩個類:SimpleTriger和CronTriger。當只觸發一次或者週期性觸發選擇SimpleTriger。當定時觸發時可以選擇CronTriger。

  Calendar:作為時間點的集合。

  Scheduler:任務排程容器,Scheduler中註冊Triger和JobDetail,將Triger和JobDetail關聯起來。

  實現任務排程步驟:

  1、建立任務,並設定名稱和組名。2、建立觸發器,並設定名稱和組名。3、對觸發器設定時間規則。4、定義任務排程容器,將觸發器與任務加入容器,並這隻關聯。

  SimpleTriger任務排程例項:

  建立任務類

package scheduler;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class SimpleJob implements Job{

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		// TODO Auto-generated method stub
		System.out.println("定時任務排程=================");
	}
	
}

  將任務與觸發器關聯

/**
 * 
 */
/**
 * @author Administrator
 *
 */
package scheduler;

import java.util.Collection;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import sun.java2d.pipe.SpanShapeRenderer.Simple;

public class SimpleTriggerRunner {
	public static void main(String[] args){
		try{
			JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("job_1", "group_1").build();
			SimpleTrigger trigger = TriggerBuilder
					.newTrigger()
					.withIdentity("trigger_1","group_triger")
					.startNow()
					.withSchedule(SimpleScheduleBuilder
							.simpleSchedule()
							.withIntervalInSeconds(5)
							.repeatForever())
					.build();
			SchedulerFactory factory = new StdSchedulerFactory();
			Scheduler scheduler = factory.getScheduler();
			scheduler.scheduleJob(jobDetail, trigger);
			scheduler.start();
		}catch(Exception e){
			e.printStackTrace();
		}		
	}
}

  CronTriger實現任務排程例項:

  

import java.util.Collection;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import sun.java2d.pipe.SpanShapeRenderer.Simple;

public class SimpleTriggerRunner {
	public static void main(String[] args){
		try{
			JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("job_1", "group_1").build();
			SimpleTrigger trigger = TriggerBuilder
					.newTrigger()
					.withIdentity("trigger_1","group_triger")
					.startNow()
					.withSchedule(SimpleScheduleBuilder
							.simpleSchedule()
							.withIntervalInSeconds(5)
							.repeatForever())
					.build();
			SchedulerFactory factory = new StdSchedulerFactory();
			Scheduler scheduler = factory.getScheduler();
			scheduler.scheduleJob(jobDetail, trigger);
			scheduler.start();
		}catch(Exception e){
			e.printStackTrace();
		}		
	}
}

  Spring中使用quartz

  建立JobDetailBean

  步驟:

  1、建立JobDetail例項JobDetailBean。對JobDetailBean進行屬性設定,jobClass:用來指定任務;beanName:設定任務的名稱;JobDataAsMap為任務的JobDataMap提供值;applicationContextJobDataKey:為Job提供applicationContext。2、建立Trigger觸發器,主要是通過SimpleTriggerBean、CronTriggerBean和CronTriggerFactoryBean進行建立,需要將任務例項配置其中。3、通過SchedulerFactoryBean類配置Scheduler,將Trigger加入Schedulerde的Trigger列表中。

  例項:

  定義任務類

package scheduler;

import java.util.Map;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

import bean.User;
@Component("myJob")
public class MyJob{

	public void myexecute() {
		// TODO Auto-generated method stub
		System.out.println("Spring開始任務排程=========");
		System.out.println("Spring結束任務排程==========");
	}
	
}

   將任務加入觸發器,並設定排程時間。將觸發器加入排程。

<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    http://www.springframework.org/schema/mvc
                    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util-3.0.xsd"
                    >
<context:component-scan base-package="scheduler"/>
<!-- jobDetail -->
<bean id="jobnew" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="myJob"/>
    <property name="targetMethod" value="myexecute"/>
<!--false表示等上一個任務執行完後再開啟新的任務-->
    <property name="concurrent" value="false"/>
</bean>
<!-- Trigger-->
<bean id="oceanStatusCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="jobnew"/>
    <property name="cronExpression" value="0 */2 * * * ?"/>
</bean>
<!--Scheduler -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="oceanStatusCronTrigger"/>
        </list>
    </property>
</bean>    
</beans>

  Spring中使用Timer

  Timer

  當使用排程比較頻繁時,可以考慮使用Timer,並不適合固定時間點例如每週週一上午八點的排程策略。但是對於長時間執行的任務來說,該排程會嚴重影響效能,因為每一個Timer是在同一個執行緒,Timer中的有多個TimerTask,執行時間過長容易引起積壓。  

  TmierTask

  TimerTask相當於Job,TimerTask實現了Runnable介面,該類中主要有三個方法:任務執行邏輯,執行時間,取消執行。
  實現任務排程的步驟:
  1、建立TimerTask類。2、建立Timer類。3、將TimerTask例項註冊到Timer中。  

  例項

  建立任務例項

package scheduler;

import java.util.TimerTask;

public class SimpleTimerTask extends TimerTask{
	private int count=0;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("執行緒執行次數========="+count);
		count++;
		if(count>10){
			cancel();
		}
	}
}

  將任務註冊到Timer中

package scheduler;

import java.util.Timer;
import java.util.TimerTask;

public class TimerRunner {

	public static void main(String[] args){
		Timer timer = new Timer();
		TimerTask timerTask = new SimpleTimerTask();
		timer.schedule(timerTask, 1000, 2000);
	}
}

  Spring對Timer的使用

   建立任務類

package scheduler;

import org.springframework.stereotype.Component;

@Component("myService")
public class MyService {

	public void timerTest(){
		System.out.println("開始使用TimerTask=========");
	}
}

  將任務類封裝為TimerTask,並將TimerTask設定定時規則,將規則注入Timer。

<!-- 通過生成任務TimerTask -->
<bean id="timerTask" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean" 
	p:targetObject-ref="myService"
	p:targetMethod="timerTest"/>
<!-- 定義排程規則 -->
<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"
	p:timerTask-ref="timerTask"
	p:delay="1000"
	p:period="1000"/>
<!-- 將排程規則放入排程佇列 -->
<bean id="timerFactoryBean" class="org.springframework.scheduling.timer.TimerFactoryBean">
	<property name="scheduledTimerTasks">
	<list>
		<ref bean="scheduledTask"/>
	</list>
	</property>
	</bean>

  Spring中使用Executor

    Executor主要有兩個任務:任務提交和任務執行。Executor只有一個方法:void execute(Runnable command),該方法接收任何實現了Runnable的例項。

    Executor的簡單實現:

package scheduler;

import java.util.concurrent.Executor;

public class SimpleExecutor implements Executor{

	@Override
	public void execute(Runnable command) {
		// TODO Auto-generated method stub
		command.run();
	}

}

    可以為每個任務建立一個執行緒:

package scheduler;

import java.util.concurrent.Executor;

public class TaskExecutor implements Executor{

	@Override
	public void execute(Runnable command) {
		// TODO Auto-generated method stub
		//為每一個任務重新建立一個執行緒
		new Thread(command).start();
	}

}

    可以將任務放到執行緒池排程中,每一個任務會通過獲取執行緒,進行任務處理。SchedulerThreadPoolExecutor繼承ThreadPoolExecutor,ThreadPoolExecutor繼承了Executor和ExecutorService。而SchedulerThreadPoolExecutor通過newFixedThreadPool(int nThreads)建立一個執行緒池進行任務處理。

    使用例項:

package scheduler;

public class SimpleRunnable implements Runnable{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("開啟任務執行==========");
	}

}

  

package scheduler;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ExecutorExample {

	private Executor executor;
	public void setExecutor(Executor executor){
		this.executor = executor;
	}
	
	public void executeTask(){
		for(int i=0;i<6;i++){
			executor.execute(new SimpleRunnable());
		}
	}
	public static void main(String args){
		ExecutorExample ee = new ExecutorExample();
		ee.setExecutor(Executors.newFixedThreadPool(3));
		ee.executeTask();
	}
}

Spring任務排程的註解支援

  @Schedule的例項

   配置定時任務:

<?xml version="1.0" encoding="UTF-8"?>
<beans
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 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-4.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-4.0.xsd
                    http://www.springframework.org/schema/mvc
                    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util-4.0.xsd
                    http://www.springframework.org/schema/task
                    http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<context:component-scan base-package="scheduler"/>
<!-- 啟用註解驅動的定時任務 -->
<task:annotation-driven scheduler="myScheduler"/>
<!-- 推薦配置執行緒池,若不配置多工下會有問題。後面會詳細說明單執行緒的問題。 -->
<task:scheduler id="myScheduler" pool-size="5"/>
</beans>

  建立任務類

package scheduler;

import java.util.Map;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

import bean.User;
@Component("myJob")
public class MyJob{

	public void myexecute() {
		// TODO Auto-generated method stub
		System.out.println("Spring開始任務排程=========");
		System.out.println("Spring結束任務排程==========");
	}
	
}