讲解Trigger触发器

发表时间:2018-01-11 17:02:18 浏览量( 26 ) 留言数( 0 )

学习目标:

1、了解触发器的基本属性

2、了解触发器的优先级设置

3、了解触发器的日历的概念


学习过程:

一、一般触发器的属性

“jobKey” property 触发器执行的job的标识。

“startTime” property 表示触发器进入了一个有效时间内的开始时间。.

“endTime” property indicates 表示触发器已经不再有效了。


二、Quartz Trigger Priority 触发器优先级

当多个触发器在一个相同的时间内触发,并且调度引擎中的资源有限的情况下,那么具有较高优先级的触发器先触发。有时,当有多个Triggers时,Quartz没有足够的资源来同时立即处理scheduled的trigger.所以你可能要控制哪个先执行.  在这种情况下,你要设置Trigger的priority,如果N个triggers不会同时触发.但此时只有有限的几个线程可用.这时会先处  理级别高的trigger.如果你没有设置级别,默认为5。前面我们简单说过Quartz有自己的线程池,在同一时间可以根据线程数启动任务,但是如果同时启动的任务超过了预置的线程数,哪一个触发器的任务先执行呢。就是根据优先级判断的,配置线程数是:org.quartz.threadPool.threadCount = 1,这个可以自己根据需要配置的。简单的实例如下:

定义三个job,分别是TestJob1、TestJob2、TestJob3,代码都是一样的。

public class TestJob1 implements Job{

	public void execute(JobExecutionContext context) throws JobExecutionException {
		JobKey key = context.getJobDetail().getKey();
		
		System.out.println("key:"+key+",date="+new Date());
		
	}

}

运行测试类:

public class QuartzTest {

	public static void main(String[] args) {

		try {
			SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

			Scheduler sched = schedFact.getScheduler();

			sched.start();

			JobDetail job1 = newJob(TestJob1.class).withIdentity("TestJob1", "group1").build();
			JobDetail job2 = newJob(TestJob2.class).withIdentity("TestJob2", "group2").build();
			JobDetail job3 = newJob(TestJob3.class).withIdentity("TestJob3", "group3").build();

			Date startTime = futureDate(5, IntervalUnit.SECOND);

			Trigger trigger1 = newTrigger().withIdentity("Priority7 Trigger5SecondRepeat").startAt(startTime)
					.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).withPriority(1).build();

			Trigger trigger2 = newTrigger().withIdentity("Priority5 Trigger10SecondRepeat").startAt(startTime)
					.withPriority(5).withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();

			Trigger trigger3 = newTrigger().withIdentity("Priority10 Trigger15SecondRepeat").startAt(startTime)
					.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).withPriority(10).build();

			// Tell quartz to schedule the job using our trigger
			sched.scheduleJob(job1, trigger1);
			sched.scheduleJob(job2, trigger2);
			sched.scheduleJob(job3, trigger3);

		} catch (SchedulerException se) {
			se.printStackTrace();
		}
	}
}

看一下输出,前面可能还有点乱,后面基本就是按照优先级的顺序输出了:

attcontent/1fb7faed-ccc3-4a38-acf0-d7f9c4c1bc8a.png

二、Calendar日历的使用

Quartz Calendar和Java原始的Calendar是不一样的。Quartz Calendar对象在trigger被存储到scheduler时与trigger相关联。Calendar对于在trigger触发日程中的采用批量世间非常有用。例如:你想要创建一个在每个工作日上午9:30触发一个触发器,那么就添加一个排除所有节假日的日历。Calendar可以是任何实现Calendar接口的序列化对象。Calendar的接口如下:

public interface Calendar {

	  public boolean isTimeIncluded(long timeStamp);

	  public long getNextIncludedTime(long timeStamp);

	}

这些方法的参数都是DateTime型,你可以猜想出,它们的时间戳是毫秒的格式。这意味日历能够排除毫秒精度的时间

常见的实现类:

AnnualCalendar This implementation of the Calendar excludes a set of days of the year.

BaseCalendar This implementation of the Calendar may be used (you don't have to) as a base class for more sophisticated one's.

CronCalendar This implementation of the Calendar excludes the set of times expressed by a given CronExpression.

DailyCalendar This implementation of the Calendar excludes (or includes - see below) a specified time range each day.

HolidayCalendar This implementation of the Calendar stores a list of holidays (full days that are excluded from scheduling).

MonthlyCalendar This implementation of the Calendar excludes a set of days of the month.

WeeklyCalendar This implementation of the Calendar excludes a set of days of the week.

一、AnnualCalendar

这个日历可以设置一组日期的集合,当与trigger关联后,trigger在设定的这些日期之内都不会触发。年的设置是不起效的。先定义AnnualCalendar,然后放到sched.addCalendar("nodays", holidays, false, false);中,并与trigger关联modifiedByCalendar("nodays"),当日期到达上面设置的日期的时候,触发器不触发。

代码如下:

public class QuartzTest {

	public static void main(String[] args) {

		try {
			SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

			Scheduler sched = schedFact.getScheduler();

			// Add the holiday calendar to the schedule
			AnnualCalendar holidays = new AnnualCalendar();
			//设置为今天,你会发现都不会执行了
			Calendar calendar = new GregorianCalendar(2018, 0, 11);
			holidays.setDayExcluded(calendar, true);
			sched.addCalendar("noexecutedays", holidays, false, false);

			sched.start();

			// define the job and tie it to our HelloJob class
			JobDetail job = newJob(StateJob.class).withIdentity("StateJobName1", "StateJobgroup1").storeDurably(true)
					.requestRecovery(true).usingJobData("count", 1).build();

			// Trigger the job to run now, and then every 3 seconds
			Trigger trigger = newTrigger().withIdentity("myTrigger", "group1").startNow()
					.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever())
					.build();

			// Tell quartz to schedule the job using our trigger
			sched.scheduleJob(job, trigger);
		} catch (SchedulerException se) {
			se.printStackTrace();
		}
	}
}

2、CronCalendar

Cron表达式日历,可以写一个表达式来排除一个时间范围,比如可以设置为排除所有的时间,但是工作时间除外,也就是 在早8点-晚5点触发,其他时间暂停

CronCalendar calendar = new CronCalendar("* * 0-7,18-23 ? * *");

sched.addCalendar("business", calendar, false, false);



3、DailyCalendar

时间范围日历,定义一个时间范围,可以让触发器在这个时间范围内触发,或者在这个时间范围内不触发,每一个DailyCalendar的实例只能设置一次时间范围,并且这个时间范围不能超过一天的边界,比如你不能定义一个时间范围是(晚上8点至第二天早上5点),如果invertTimeRange这个属性等于false(默认),那么定义的时间范围内触发器不会触发,相反如果invertTimeRange=true 那么只有在这个时间范围内触发器才会触发

Calendar s = Calendar.getInstance();

s.setTime(new Date());

        

Calendar e = Calendar.getInstance();

e.setTime(futureDate(10, IntervalUnit.SECOND));

        

DailyCalendar dailyCalendar = new DailyCalendar(s, e);

//DailyCalendar dailyCalendar = new DailyCalendar("20:57:00", "20:59:00");

dailyCalendar.setInvertTimeRange(true);

sched.addCalendar("dailyCalendar", dailyCalendar, false, false);


4、HolidayCalendar

该日历与AnnualCalendar一致,区别就是设置的year是有效的,也就是说如果你希望在未来的10年中 7月4日这天 这个日历生效,那么你需要添加10个日期,分别是 2014-7-4 ,2015-7-4...... 2024-7-4 这样才行。


HolidayCalendar holidays = new HolidayCalendar();

Calendar calendar = new GregorianCalendar(2014, 7, 21);

holidays.addExcludedDate(calendar.getTime());

sched.addCalendar("holidays", holidays, false, false);

下面是查询排除日期的算法,getStartOfDayJavaCalendar是把分秒时毫秒都去掉 只留年月日 然后判断日期是否排除


5、MonthlyCalendar

月日历,你可以定义一个月当中的若干天,例如你可以设置每个月的第一天触发器不进行触发,当然你还可以定义一个月当中的任何一天。


下面例子给出每个月2,3,4号不触发的日历


MonthlyCalendar monthlyCalendar = new MonthlyCalendar();

monthlyCalendar.setDayExcluded(2, true);

monthlyCalendar.setDayExcluded(3, true);

monthlyCalendar.setDayExcluded(4, true);

sched.addCalendar("monthlyCalendar", monthlyCalendar, false, false);


6、WeeklyCalendar

星期几的配置。你可以设置星期几的时候不进行触发

WeeklyCalendar weeklyCalendar=new WeeklyCalendar();

weeklyCalendar.setDayExcluded(2, true);

weeklyCalendar.setDayExcluded(3, true);

weeklyCalendar.setDayExcluded(4, true);

sched.addCalendar("weeklyCalendar", weeklyCalendar, false, false);