• Java 定时任务 & 任务调度


    任务调度是指基于 给定时间点给定时间间隔 或者 给定执行次数 自动执行任务。

    方式1:通过 Thread 来实现

    例如如下的代码,可以每隔 1000 毫秒做一次打印操作。

    public class Job_Schedule_Test1 {
        public static void main(String[] args) {
            new JobThread().start();
        }
    }
    
    class JobThread extends Thread {
        public void run() {
            while (true) {
                System.out.println("Test: " + Calendar.getInstance().getTime());
    
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                }
            }
        }
    }
    

    输出如下:

    Test: Wed Feb 22 14:33:57 CST 2017
    Test: Wed Feb 22 14:33:58 CST 2017
    Test: Wed Feb 22 14:33:59 CST 2017
    Test: Wed Feb 22 14:34:00 CST 2017
    Test: Wed Feb 22 14:34:01 CST 2017

    方式2:通过 Timer 来实现

    • 自定义一个任务,继承于 TimerTask,重写 run 方法
    • 利用 java.util.Timer 实现任务调度
    public class Job_Schedule_Test2 {
        public static void main(String[] args) {
            Timer timer = new Timer();
            long delay = 2000;
            long interval = 1000;
    
            // 从现在开始 2 秒钟之后启动,每隔 1 秒钟执行一次
            timer.schedule(new JobTask(), delay, interval);
        }
    }
    
    class JobTask extends TimerTask {
        public void run() {
            System.out.println("Test: " + Calendar.getInstance().getTime());
        }
    }
    

    输出如下:

    Test: Wed Feb 22 15:02:15 CST 2017
    Test: Wed Feb 22 15:02:16 CST 2017
    Test: Wed Feb 22 15:02:17 CST 2017
    Test: Wed Feb 22 15:02:18 CST 2017
    Test: Wed Feb 22 15:02:19 CST 2017

    Timer 的设计核心是一个 TaskList 和一个 TaskThread
    Timer 将接收到的任务丢到自己的 TaskList 中,TaskList 按照 Task 的最初执行时间进行排序。TimerThread 在创建 Timer 时会启动成为一个守护线程。这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。

    Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
    例如我们指定每隔 1000 毫秒执行一次任务,但是可能某个任务执行花了 5000 毫秒,因此导致后续的任务并不能按时启动执行。

    方式3:通过 ScheduledExecutorService 来实现

    鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutorService
    其设计思想是,每一个被调度的任务都会 由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。
    需要注意的是,只有当任务的执行时间到来时,ScheduledExecutorService 才会真正启动一个线程,其余时间 ScheduledExecutorService 都是在轮询任务的状态。

    public class Job_Schedule_Test3 {
        public static void main(String[] args) {
            ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
            long delay = 2;
            long interval = 1;
    
            // 从现在开始 2 秒钟之后启动,每隔 1 秒钟执行一次
            service.scheduleAtFixedRate(
                    new JobTask2(), delay,
                    interval, TimeUnit.SECONDS);
        }
    }
    
    class JobTask2 implements Runnable {
        public void run() {
            System.out.println("Test: " + Calendar.getInstance().getTime());
        }
    }
    

    输出如下:

    Test: Wed Feb 22 15:19:05 CST 2017
    Test: Wed Feb 22 15:19:06 CST 2017
    Test: Wed Feb 22 15:19:07 CST 2017
    Test: Wed Feb 22 15:19:08 CST 2017
    Test: Wed Feb 22 15:19:09 CST 2017

    用 ScheduledExecutorService 和 Calendar 实现复杂任务调度

    TimerScheduledExecutor 都仅能提供基于开始时间与重复间隔的任务调度,不能胜任更加复杂的调度需求。
    比如,设置每星期二的 16:38:10 执行任务。我们可以借助 Calendar 间接实现该功能。
    其核心在于根据当前时间推算出最近一个星期二 16:38:10 的绝对时间,然后计算与当前时间的时间差,作为调用 ScheduledExceutor 函数的参数。

    具体参见 几种任务调度的 Java 实现方法与比较

    方式4:通过 Quartz 来实现

    Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do.

    示例如下:

    public class QuartzJob implements org.quartz.Job {
        public QuartzJob() {
        }
    
        public void execute(JobExecutionContext arg0) throws JobExecutionException {
            System.out.println("Test: " + Calendar.getInstance().getTime());
        }
    }
    
    import org.quartz.*;
    import org.quartz.impl.StdSchedulerFactory;
    import static org.quartz.JobBuilder.*;
    import static org.quartz.TriggerBuilder.*;
    import static org.quartz.SimpleScheduleBuilder.*;
    
    public class Job_Schedule_Test4 {
        public static void main(String[] args) throws SchedulerException {
            // Grab the Scheduler instance from the Factory
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    
            // define the job and tie it to our MyJob class
            JobDetail job = newJob(QuartzJob.class)
                    .withIdentity("job1", "group1")
                    .build();
    
            // Trigger the job to run now, and then repeat every 40 seconds
            Trigger trigger = newTrigger()
                    .withIdentity("trigger1", "group1")
                    .startNow()
                    .withSchedule(simpleSchedule()
                            .withIntervalInSeconds(1)
                            .repeatForever())
                    .build();
    
            // Tell quartz to schedule the job using our trigger
            scheduler.scheduleJob(job, trigger);
    
            // and start it off
            scheduler.start();
        }
    }
    

    方式5:通过 JCronTab 来实现

    具体参见 几种任务调度的 Java 实现方法与比较


    引用:
    Java实现定时任务的三种方法
    几种任务调度的 Java 实现方法与比较



    作者:专职跑龙套
    链接:https://www.jianshu.com/p/aa7b7f50b4b0
    來源:简书

  • 相关阅读:
    解决xcode5升级后,Undefined symbols for architecture arm64:问题
    第8章 Foundation Kit介绍
    app 之间发送文件 ios
    iphone怎么检测屏幕是否被点亮 (用UIApplication的Delegate)
    CRM下载对象一直处于Wait状态的原因
    错误消息Customer classification does not exist when downloading
    How to resolve error message Distribution channel is not allowed for sales
    ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼
    有了Debug权限就能干坏事?小心了,你的一举一动尽在系统监控中
    SAP GUI和Windows注册表
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/9960630.html
Copyright © 2020-2023  润新知