Timer類注意事項
Java的一個Timer物件可以執行多個Timertask任務,但是一個Timer物件本身只有一個執行緒,如果向他提交多個task,並且某個task相當耗時的話,其他的task即使到了執行時間,仍然會等之前的task執行完畢。更有問題,如果前一個task丟擲了異常導致執行緒終止,後面的task將無法執行。
Timer 是一種定時器工具,用來在一個後臺執行緒計劃執行指定任務,這些任務可以被執行一次,也可以被定期執行。每個 Timer 物件對應一個後臺執行緒,順序地執行所有計時器任務。如果完成某個計時器任務的時間太長,那麼它會“獨佔”計時器的任務執行執行緒,從而可能延遲後續任務的執行。對 Timer 物件最後的引用完成並且所有未處理的任務都已執行完成後,計時器的任務執行執行緒會正常終止(並且成為垃圾回收的物件)。TimerTask是一個抽象類,實現了Runable介面,它的子類代表一個可以被Timer計劃的任務。
Timer類的schedule和scheduleAtFixedRate的區別:
schedule和 scheduleAtFixedRate的區別在於,schedule以固定的相對時間間隔執行,如果某一次執行被延時了,往後的執行的執行時間也會相對延時;而scheduleAtFixedRate是以絕對的時間間隔執行,如果某一次執行被延時,它的後一次執行的延時將會縮短(scheduleAtFixedRate會把已經過去的時間也作為週期執行)。schedule注重的是時間間隔的穩定,而scheduleAtFixedRate注重的是執行頻率的穩定。
示例如下:
timerForDims = new Timer();
timerForDims.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
updateDim();
}
}, Calendar.getInstance().getTime(), 10 * 60 * 1000);
//每日3點從離線表裡讀取老使用者ID存入redis
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 3);
String beforeDay = TimeUtil.getBeforeDay();
RefreshHiveOldUsers(beforeDay);
timerForOldUsers = new Timer();
timerForOldUsers.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
RefreshHiveOldUsers(beforeDay);
} catch (SQLException e) {
logger.error("RefreshOldUser: " + e.getMessage());
}
}
}, calendar.getTime(), 24 * 60 * 60 * 1000);