Java任务调度的几种解决方案(定时任务)


Java任务调度的几种解决方案(定时任务)

一、JDK原生定时工具Timer

1.定时任务调度:基于给定的时间点、给定的时间间隔、给定的执行次数的自动执行的任务

2.Timer位于java.util包下,内部仅包含一个后台线程(TimeThread)对多个业务任务(TimeTask)进行定时、定频率的调度。

3.schedule的四种用法和shceduleAtFixedRate的两种用法:

void schedule(TimerTask task, long delay);

void schedule(TimerTask task, Date time);

void schedule(TimerTask task, long delay, long period);

void schedule(TimerTask task, Date firstTime, long period);

void scheduleAtFixedRate(TimeTask task,  long delay, long period );

void scheduleAtFixedRate(TimeTask task,  Date firstTime, long period );

  参数说明:

task:所要实行的任务(需要继承TimeTask的run()方法)

time/firstTime:首次执行任务的时间

period:周期性执行task的时间间隔,单位是毫秒

delay:执行task任务前延迟的时间,单位是毫秒

4.注意事项

    4.1.如果time/firstTime指定在当前时间之前,立刻执行task;

    4.2.scheduleAtFixedRate在任务开始时向后延迟一个period的时间执行下一次任务

      而schedule在任务结束时向后延迟一个period的时间执行下一次任务

    4.3.如果TimeTask抛出RuntimeException,那么Timer会停止所有任务的运行

    4.4.单线程无法满足并发任务的需求,所有的任务都是串行执行意味着同一时间只能有一个任务得到执行

5.其他

Timer.cancel():终止Timer计时器,丢弃当前所有已安排的任务

TimerTask.cancel():终止TimeTask

Timer.purge():从计时器的任务列表中移除已取消的任务,并返回个数

6.Demo

public classTimerDemo {

    public static voidmain(String[] args) {

        Timer timer =new Timer();

        //timer.schedule(new MyTask(),new Date(),20000);

        timer.schedule(new MyTask(), 30000, 20000);

        //timer.cancel();

    }

}

class MyTaskextends TimerTask{

    @Override

    public voidrun() {

        System.out.println("execute time start :"

                +new SimpleDateFormat().format(

                        this.scheduledExecutionTime()

                )

        );

        try{

            Thread.sleep(2000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        //this.cancel();

    }

}

二、JDK对定时任务调度的线程池支持:ScheduleExecutorService

    虽然ScheduleExcutorServiced对Timer进行了线程池的改进,但无法满足复杂的定时任务调度场景。

Demo:

public class ScheduleExecutorServiceDemo{

    public static voidmain(String[] args) {

        ScheduledExecutorService scheduledExecutorService=

                Executors.newScheduledThreadPool(10);

        scheduledExecutorService.scheduleAtFixedRate(

                new MyTask(),2000,2000, TimeUnit.MILLISECONDS

        );

    }

}

classMyTask implementsRunnable{

   @Override

   public voidrun() {

     System.out.println("execute time start :”+new Date());

   }

}

三、Quartz(OpenSymphony)

1.作为Spring默认的调度框架,Quartz是纯Java实现的。

      由于Quartz强大的调度功能、灵活的使用方式、还具有分布式集群能力,可以说Quartz出马轻松搞定一切任务调度服务。

2.相较于Timer,Quartz增加的功能:

    2.1.持久性作业:保持调度定时的状态

    2.2.作业管理:对调度作业进行有效的管理

3.Demo

public classPrintWordJob implementsJob {

    @Override

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException{

        Calendar calendar= jobExecutionContext.getCalendar();

        String dateFormat =new SimpleDateFormat("yy-mm-dd hh:mm:ss").format(calendar);

        System.out.println("打印文字时间:"+dateFormat+",打印内容:Hello Job-"+new Random().nextInt(100));

    }

}

public static void main(String[] args) throws SchedulerException, InterruptedException{

    //1.创建调度器Scheduler

    SchedulerFactory schedulerFactory=new StdSchedulerFactory();

    Scheduler scheduler=schedulerFactory.getScheduler();

    //2.创建JobDetail实例,并与PrintWordJob类绑定(Job执行内容)

    JobDetail jobDetail= JobBuilder.newJob(PrintWordJob.class)

            .withIdentity("myFirstJob","myGroup")

            .build();

    //3.构建Trigger实例,设置每隔三秒执行一次

    Trigger trigger=TriggerBuilder.newTrigger()

            .withIdentity("trigger1","triggerGroup1")

            .startNow()

            .withSchedule(

                    SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever()

            ).build();

    //4.执行

    scheduler.scheduleJob(jobDetail,trigger);

    System.out.println("==========================scheduler start !======================");

    scheduler.start();

    //5.睡眠

    TimeUnit.MINUTES.sleep(1);

    scheduler.shutdown();

    System.out.println("==========================scheduler shutdown !======================");

}

4.JobJobDetail 

4.1.Job是Quartz中的一个接口,接口下只有execute方法,在该方法中编写业务逻辑

4.2.JobDetail用来绑定Job并为实例提供属性:name、group、jobClass、jobDataMap

      JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会先拿到对应的Job并创建Job实例,再去执行Job中的exxcute方法的内容。任务执行结束后关联的Job对象实例会被释放,且会被JVM GC清除。

4.3.JobDetail的任务就是在Scheduler执行时创建一个新的Job实例,避免并发直接访问同一Job实例。


5.JobExecutionContext

JobExecutionContext包含Quartz运行时的环境以及Job本身的详细数据信息。当Schedule调度执行了一个Job的时候,就会将JobExecutionContext传递到该Job的execute()中,Job就可以通过JobExecutionCOntext对象获取信息。

6.JobDataMap

JobDataMap实现了JDK的Map接口,可以以key-value的形式存储数据。JobDetail、Trigger都可以使用JobDataMap来设置一些参数信息,Job执行execute()方法的时候,JobExecutionContext可以获取到JobDataMap里的信息。

Demo:

初始化JobDetail时:

JobDetail jobDetail= JobBuilder.newJob(PrintWordJob.class)

        .withIdentity("myFirstJob", "myGroup")

        .usingJobData("key", "value")

        .build();

Job实例中获取

Object value= jobExecutionContext.getMergedJobDataMap().get("key");

7.Trigger:Trigger是Quartz的触发器,会去通知Scheduler合适去执行对应的Job

new Trigger().startAt():设置触发器首次被触发的时间;

new Trigger().endAt():设置触发器接触触发的时间;

new Trigger().startNow():设置触发器启动后即刻触发

7.1. TriggerWithSimpleSchedule

Demo:

Date startDate= new Date();

startDate.setTime(startDate.getTime() +5000);

Date endDate= new Date();

endDate.setTime(startDate.getTime() +5000);

Trigger trigger =TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")

        .usingJobData("trigger1", "这是jobDetail1的trigger")

        .startNow()//立即生效

        .startAt(startDate)

        .endAt(endDate)

        .withSchedule(SimpleScheduleBuilder.simpleSchedule()

                .withIntervalInSeconds(1)//每隔1s执行一次

                .repeatForever()).build();//一直执行

7.2. CronTrigger(常用)

CronTrigger基于日历的作业调度,而SimpleTrigger是精准指定间隔。

Cron表达式:[秒][分][时][日][月][周][年]

Demo:

CronTrigger cronTrigger= TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")

        .usingJobData("trigger1", "这是jobDetail1的trigger")

        .startNow()//立即生效

        .startAt(startDate)

        .endAt(endDate)

        .withSchedule(CronScheduleBuilder.cronSchedule("* 30 10 ? * 1/5 2018"))

        .build();

你可能感兴趣的:(Java任务调度的几种解决方案(定时任务))