天天看點

ScheduledExecutorService定時任務1.之是以使用ScheduledExecutorService而不使用Timer是由于我的idea軟體和我說這個更好

1.之是以使用ScheduledExecutorService而不使用Timer是由于我的idea軟體和我說這個更好

好了實際是Timer的内部隻有一個線程,如果有多個任務的話就會順序執行,這樣我們的延遲時間和循環時間就會出現問題。

ScheduledExecutorService是線程池,是以就不會出現這個情況,在對延遲任務和循環任務要求嚴格的時候,就需要考慮使用ScheduledExecutorService了。

由于我是在web項目中碰見的這個需求是以在這裡貼代碼

package com.ywj.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TimerManage {
    //線程池能按時間計劃來執行任務,允許使用者設定計劃執行任務的時間,int類型的參數是設定
   //線程池中線程的最小數目。當任務較多時,線程池可能會自動建立更多的工作線程來執行任務
    //此處的話使用Executors.newSingleThreadScheduledExecutor()更好是以使用的而不是Executors.newScheduledThreadPool(1)。
  private   ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
  //private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
    public TimerManage(){
    //設定時間格式
    try {
        //設定從此刻時間開始  建議設定未來時間,不然項目啟動的話就會先執行一次
        DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        Date date2 = getThisWeekSaturday(date);//擷取下星期6的時間
        if (date.getTime() >= date2.getTime()) {//如果目前時間不小于周六的時間,
            Calendar cal = Calendar.getInstance();
            cal.setTime(date2);
            cal.add(Calendar.WEEK_OF_MONTH, +1);//周數加一
            date2 = cal.getTime();
        }
        long period=60*60*24*7*1000;//時間間隔
//        command:執行線程
//        initialDelay:初始化延時
//        period:兩次開始執行最小間隔時間
//        unit:計時機關 是period和initialDelay的時間大家一定要注意
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("執行的方法");
            }
        },date2.getTime()-date.getTime(),period, TimeUnit.MILLISECONDS);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

    /**
     * 關閉
     */
    public void close(){
        System.out.println("關閉了");
    this.executorService.shutdown();
}

    /**
     * 擷取這個星期六是那一天
     * @param date
     * @return
     */
    public static Date getThisWeekSaturday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 獲得目前日期是一個星期的第幾天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        //設定時間為淩晨2點
        cal.set(Calendar.HOUR_OF_DAY, 02);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        // 設定一個星期的第一天,按中國的習慣一個星期的第一天是星期一
        //這裡設定為星期六的話就會當作星期六是每個星期第一天
        cal.setFirstDayOfWeek(Calendar.SATURDAY);
        // 獲得目前日期是一個星期的第幾天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根據月曆的規則,給目前日期減去星期幾與一個星期第一天的內插補點就會得到
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }
}
           
scheduleAtFixedRate方法的參數解釋
 command:執行線程
 initialDelay:初始化延時
 period:兩次開始執行最小間隔時間
 unit:計時機關 是period和initialDelay的時間大家一定要注意不然很有可能三十年執行一次

           

然後是監聽器的代碼

package com.ywj.util;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class BeginRun implements ServletContextListener {

    TimerManage timerManage=null;

    //啟動執行
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("任務開始");
         timerManage = new TimerManage();
    }
  //銷毀執行
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    if(this.timerManage!=null){
        timerManage.close();
    }
    }

}
           

web.xml的監聽器配置

<listener>
  <listener-class>com.ywj.util.BeginRun</listener-class>
  </listener>