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>