zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/hongdada/p/6532894.html
Copyright © 2011-2022 走看看