• Java任务调度


    1.Timer

    package com.qhong;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class Main {
        public static void main(String[] args) {
            Timer timer = new Timer();
            long delay1 = 1 * 1000;
            long period1 = 1000;
            // 从现在开始 1 秒钟之后,每隔 1 秒钟执行一次 job1
            timer.schedule(new TimerTest("job1" +DateUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss")), delay1, period1);
            long delay2 = 2 * 1000;
            long period2 = 2000;
            // 从现在开始 2 秒钟之后,每隔 2 秒钟执行一次 job2
            timer.schedule(new TimerTest("job2"), delay2, period2);
        }
    }
    
    class TimerTest extends TimerTask {
        private String jobName = "";
        public TimerTest(String jobName) {
            super();
            this.jobName = jobName;
        }
    
        @Override
        public void run() {
            System.out.println("execute " + jobName);
        }
    }
    
    class DateUtils {
        /** 时间格式(yyyy-MM-dd) */
        public final static String DATE_PATTERN = "yyyy-MM-dd";
        /** 时间格式(yyyy-MM-dd HH:mm:ss) */
        public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
        public static String format(Date date) {
            return format(date, DATE_PATTERN);
        }
    
        public static String format(Date date, String pattern) {
            if(date != null){
                SimpleDateFormat df = new SimpleDateFormat(pattern);
                return df.format(date);
            }
            return null;
        }
    }
    execute job12017-03-10 19:48:45
    execute job2
    execute job12017-03-10 19:48:45
    execute job12017-03-10 19:48:45
    execute job2
    execute job12017-03-10 19:48:45
    execute job12017-03-10 19:48:45
    execute job2
    execute job12017-03-10 19:48:45
    execute job12017-03-10 19:48:45
    execute job2
    execute job12017-03-10 19:48:45
    execute job12017-03-10 19:48:45

    Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

    ScheduledExecutor

    package com.qhong;
    
    import java.util.Date;
    import java.text.SimpleDateFormat;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    
    public class Main {
        public static void main(String[] args) {
            ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
    
            long initialDelay1 = 1;
            long period1 = 1;
            // 从现在开始1秒钟之后,每隔1秒钟执行一次job1
            service.scheduleAtFixedRate(
                    new ScheduledExecutorTest("job1"), initialDelay1,
                    period1, TimeUnit.SECONDS);
    
            long initialDelay2 = 2;
            long delay2 = 2;
            // 从现在开始2秒钟之后,每隔2秒钟执行一次job2
            service.scheduleWithFixedDelay(
                    new ScheduledExecutorTest("job2"), initialDelay2,
                    delay2, TimeUnit.SECONDS);
        }
    }
    
    class ScheduledExecutorTest implements Runnable {
        private String jobName = "";
    
        public ScheduledExecutorTest(String jobName) {
            super();
            this.jobName = jobName;
        }
    
        @Override
        public void run() {
            System.out.println("execute "+ DateUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss") + jobName);
        }
    }
    
    class DateUtils {
        /** 时间格式(yyyy-MM-dd) */
        public final static String DATE_PATTERN = "yyyy-MM-dd";
        /** 时间格式(yyyy-MM-dd HH:mm:ss) */
        public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
        public static String format(Date date) {
            return format(date, DATE_PATTERN);
        }
    
        public static String format(Date date, String pattern) {
            if(date != null){
                SimpleDateFormat df = new SimpleDateFormat(pattern);
                return df.format(date);
            }
            return null;
        }
    }
    execute 2017-03-10 20:03:53job1
    execute 2017-03-10 20:03:54job2
    execute 2017-03-10 20:03:54job1
    execute 2017-03-10 20:03:55job1
    execute 2017-03-10 20:03:56job1
    execute 2017-03-10 20:03:56job2
    execute 2017-03-10 20:03:57job1
    execute 2017-03-10 20:03:58job1
    execute 2017-03-10 20:03:58job2
    execute 2017-03-10 20:03:59job1
    execute 2017-03-10 20:04:00job1
    execute 2017-03-10 20:04:00job2
    execute 2017-03-10 20:04:01job1
    execute 2017-03-10 20:04:02job1
    execute 2017-03-10 20:04:02job2

    展示了 ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。

    ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …;

    ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。

    由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。

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

    package com.qhong;
    
    import java.util.Calendar;
    import java.util.Date;
    import java.util.TimerTask;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    
    public class Main {
        public static void main(String[] args) {
            ScheduledExceutorTest2 test = new ScheduledExceutorTest2("job1");
            //获取当前时间
            Calendar currentDate = Calendar.getInstance();
            long currentDateLong = currentDate.getTime().getTime();
            System.out.println("Current Date = " + currentDate.getTime().toString());
            //计算满足条件的最近一次执行时间
            Calendar earliestDate = test
                    .getEarliestDate(currentDate, 3, 16, 38, 10);
            long earliestDateLong = earliestDate.getTime().getTime();
            System.out.println("Earliest Date = "
                    + earliestDate.getTime().toString());
            //计算从当前时间到最近一次执行时间的时间间隔
            long delay = earliestDateLong - currentDateLong;
            //计算执行周期为一星期
            long period = 7 * 24 * 60 * 60 * 1000;
            ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
            //从现在开始delay毫秒之后,每隔一星期执行一次job1
            service.scheduleAtFixedRate(test, delay, period,
                    TimeUnit.MILLISECONDS);
        }
    }
    
    class ScheduledExceutorTest2 extends TimerTask {
    
        private String jobName = "";
    
        public ScheduledExceutorTest2(String jobName) {
            super();
            this.jobName = jobName;
        }
    
        @Override
        public void run() {
            System.out.println("Date = "+new Date()+", execute " + jobName);
        }
    
        /**
         * 计算从当前时间currentDate开始,满足条件dayOfWeek, hourOfDay,
         * minuteOfHour, secondOfMinite的最近时间
         * @return
         */
        public Calendar getEarliestDate(Calendar currentDate, int dayOfWeek,
                                        int hourOfDay, int minuteOfHour, int secondOfMinite) {
            //计算当前时间的WEEK_OF_YEAR,DAY_OF_WEEK, HOUR_OF_DAY, MINUTE,SECOND等各个字段值
            int currentWeekOfYear = currentDate.get(Calendar.WEEK_OF_YEAR);
            int currentDayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK);
            int currentHour = currentDate.get(Calendar.HOUR_OF_DAY);
            int currentMinute = currentDate.get(Calendar.MINUTE);
            int currentSecond = currentDate.get(Calendar.SECOND);
    
            //如果输入条件中的dayOfWeek小于当前日期的dayOfWeek,则WEEK_OF_YEAR需要推迟一周
            boolean weekLater = false;
            if (dayOfWeek < currentDayOfWeek) {
                weekLater = true;
            } else if (dayOfWeek == currentDayOfWeek) {
                //当输入条件与当前日期的dayOfWeek相等时,如果输入条件中的
                //hourOfDay小于当前日期的
                //currentHour,则WEEK_OF_YEAR需要推迟一周
                if (hourOfDay < currentHour) {
                    weekLater = true;
                } else if (hourOfDay == currentHour) {
                    //当输入条件与当前日期的dayOfWeek, hourOfDay相等时,
                    //如果输入条件中的minuteOfHour小于当前日期的
                    //currentMinute,则WEEK_OF_YEAR需要推迟一周
                    if (minuteOfHour < currentMinute) {
                        weekLater = true;
                    } else if (minuteOfHour == currentSecond) {
                        //当输入条件与当前日期的dayOfWeek, hourOfDay,
                        //minuteOfHour相等时,如果输入条件中的
                        //secondOfMinite小于当前日期的currentSecond,
                        //则WEEK_OF_YEAR需要推迟一周
                        if (secondOfMinite < currentSecond) {
                            weekLater = true;
                        }
                    }
                }
            }
            if (weekLater) {
                //设置当前日期中的WEEK_OF_YEAR为当前周推迟一周
                currentDate.set(Calendar.WEEK_OF_YEAR, currentWeekOfYear + 1);
            }
            // 设置当前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND为输入条件中的值。
            currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek);
            currentDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
            currentDate.set(Calendar.MINUTE, minuteOfHour);
            currentDate.set(Calendar.SECOND, secondOfMinite);
            return currentDate;
    
        }
    }
    Current Date = Fri Mar 10 20:40:46 CST 2017
    Earliest Date = Tue Mar 14 16:38:10 CST 2017

    Quartz:

    https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/

  • 相关阅读:
    简单工厂、工厂方法和抽象工厂的学习笔记
    单一职责原则,开-闭原则,依赖倒置原则
    我对面向对象设计的理解——Java接口和Java抽象类
    高可用与负载均衡的区别
    应用交付、负载均衡(Load balancing)、高可用、F5
    四种常见的 POST 提交数据方式
    Git fetch和git pull的区别
    苹果Mac OS X显示隐藏文件的方法
    Appium教程---Client/Server Architecture
    UNIX网络编程——使用线程的TCP回射服务器程序
  • 原文地址:https://www.cnblogs.com/hongdada/p/6532894.html
Copyright © 2020-2023  润新知