本文轉載自:https://blog.csdn.net/guozebo/article/details/51090612
前言
在做後臺任務的時候經常需要實現各種各種的定時的,週期性的任務。比如每隔一段時間更新一下緩存之類的。通常週期性的任務都可以使用如下方式實現:
- class MyTimerThread extends Thread {
- @Override
- public void run() {
- while(true) {
- try {
- Thread.sleep(60*1000);
- //每隔1分鐘需要執行的任務
- doTask();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- }
Timer簡介
- /**
- * 這個方法是調度一個task,經過delay(ms)後開始進行調度,僅僅調度一次
- */
- public void schedule(TimerTask task, long delay)
- /**
- * 在指定的時間點time上調度一次
- */
- public void schedule(TimerTask task, Date time)
- 在指定的時間點time上調度一次。
- /**
- * 週期性調度任務,在delay(ms)後開始調度。
- * 並且任務開始時間的間隔爲period(ms),即“固定間隔”執行
- */
- public void schedule(TimerTask task, long delay, long period)
- /**
- * 和上一個方法類似,唯一的區別就是傳入的第二個參數爲第一次調度的時間
- */
- public void schedule(TimerTask task, Date firstTime, long period)
- public void scheduleAtFixedRate(TimerTask task, long delay, long period)
- public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)
- public static void main(String[] args) {
- TimerTask task = new TimerTask() {
- @Override
- public void run() {
- System.out.println("do task.......");
- }
- };
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- Timer timer = new Timer();
- try {
- timer.schedule(task, sdf.parse("2016-4-9 00:00:00"), 5000);
- //timer.scheduleAtFixedRate(task, sdf.parse("2016-4-9 00:00:00"),5000);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
Timer的缺陷
- public class Timer {
- // 任務隊列
- private final TaskQueue queue = new TaskQueue();
- // 處理線程
- private final TimerThread thread = new TimerThread(queue);
同樣是舉個栗子:
- public static void main(String[] args) {
- Timer timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " A: do task");
- }
- }, 0, 5*1000);
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " B: sleep");
- try {
- Thread.sleep(20*1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, 10*1000, 5000);
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " C: throw Exception");
- throw new RuntimeException("test");
- }
- }, 30*1000, 5000);
- }
ScheduledThreadPoolExecutor簡介
ScheduledThreadPoolExecutor可以說是Timer的多線程實現版本,連JDK官方都推薦使用ScheduledThreadPoolExecutor替代Timer。它是接口ScheduledExecutorService的子類,主要方法說明如下:- /**
- * 調度一個task,經過delay(時間單位由參數unit決定)後開始進行調度,僅僅調度一次
- */
- public ScheduledFuture<?> schedule(Runnable command,
- long delay, TimeUnit unit);
- /**
- * 同上,支持參數不一樣
- */
- public <V> ScheduledFuture<V> schedule(Callable<V> callable,
- long delay, TimeUnit unit);
- /**
- * 週期性調度任務,在delay後開始調度,適合執行時間比“間隔”短的任務
- * 並且任務開始時間的間隔爲period,即“固定間隔”執行。
- * 如果任務執行的時間比period長的話,會導致該任務延遲執行,不會同時執行!
- * 如果任務執行過程拋出異常,後續不會再執行該任務!
- */
- public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
- long initialDelay ,long period ,TimeUnit unit);
- /**
- * Timer所沒有的“特色”方法,稱爲“固定延遲(delay)”調度,適合執行時間比“間隔”長的任務
- * 在initialDelay後開始調度該任務
- * 隨後,在每一次執行終止和下一次執行開始之間都存在給定的延遲period
- * 即下一次任務開始的時間爲:上一次任務結束時間(而不是開始時間) + delay時間
- * 如果任務執行過程拋出異常,後續不會再執行該任務!
- */
- public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
- long initialDelay ,long delay ,TimeUnit unit);
ScheduledThreadPoolExecutor繼承自ThreadPoolExecutor,所以本質上說ScheduledThreadPoolExecutor還是一個線程池(可參考《Java線程池ThreadPoolExecutor簡介》)。它也有coorPoolSize和workQueue,接受Runnable的子類作爲任務。
- public static void main(String[] args) {
- int corePoolSize = 3;
- ScheduledExecutorService pool = Executors.newScheduledThreadPool(corePoolSize);
- pool.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " A: do task");
- }
- }, 0 ,5, TimeUnit.SECONDS);
- pool.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " B: sleep");
- try {
- Thread.sleep(20*1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, 10, 5, TimeUnit.SECONDS);
- pool.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- System.out.println(sdf.format(new Date()) + " C: throw Exception");
- throw new RuntimeException("test");
- }
- }, 30, 5, TimeUnit.SECONDS);
- }
- ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();