Java Concurrent ScheduledExecutorService:定期排程的 thread pool
先前介紹過了使用 Java Timer 來達成工作排程的效果,
也介紹了 Java 內建超簡單的 Thread Pool 機制,
今天則是要來結合這兩者,
使用 Thread Pool 裡的 Thread 來執行定期排程的工作!
在開始之前,建議的大家可以先看一下先前的相關文章:
下面的程式中首先我們在 constructor 裡取得 2條 Thread 的 Scheduled Thread Pool,
testScheduleWork、testScheduleOutdatedWork 及 testScheduleMultiWork。
完整程式碼如下:
在 testScheduleOutdatedWork 裡我們測試了如果 delay 是負的或 date 已過期的狀況,
結果會馬上執行補做喔,而不是就不做了!
像下面的結果程式開始的時間是 21:17:09,排程的時間是20秒前的 21:16:59,
所以程式一執行他馬上就補做了!
最後在 testScheduleMultiWork 裡我們是要測試 Thread Pool 的效果,
仔細觀察可以發現奇妙的結果喔!
程式在 21:28:43 開始後馬上補做 28:38, 28:39 兩個過期的工作,
而在工作執行期間 44, 45兩個工作也應該要馬上做了,
但因為 Pool 中只有兩條 Thread,所以這兩項工作被 delay,要等前面的工作做完才做。
同理我們看到最後執行的 Work 3,排程的時間是 47,但開始執行時已經是 53囉!
以上的程式供大家參考,其實還有其他好用的 schedule 方法,下面簡單介紹給大家。
若想知道更多有關 Java 時間相關的轉換、排程等應用,
或是想看其他我所寫關於 Java 的範例程式,請見:Java 教學及程式範例大全
關鍵字:Java, Thread, Pool, Executor, Executors, ThreadExecutor, ThreadPoolExecutor, ScheduledThreadPool, execute, scheduleAtFixedRate, scheduleWithFixedDelay, schedule
參考資料:
也介紹了 Java 內建超簡單的 Thread Pool 機制,
今天則是要來結合這兩者,
使用 Thread Pool 裡的 Thread 來執行定期排程的工作!
在開始之前,建議的大家可以先看一下先前的相關文章:
圖片來源:http://www.backupforall.com/backup%20scheduler.php
下面的程式中首先我們在 constructor 裡取得 2條 Thread 的 Scheduled Thread Pool,
service = Executors.newScheduledThreadPool(2);接著一次進行一項測試,分別為:
testScheduleWork、testScheduleOutdatedWork 及 testScheduleMultiWork。
完整程式碼如下:
- package werdna1222coldcodes.blogspot.com.demo.scheduleTask;
- import java.text.ParseException;
- import java.util.Date;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- public class ScheduledThreadPoolDemo {
- public static void main(String[] args) throws ParseException {
- ScheduledThreadPoolDemo demo = new ScheduledThreadPoolDemo();
- // demo.testScheduleWork();
- demo.testScheduleOutdatedWork();
- // demo.testScheduleMultiWork();
- }
- private ScheduledExecutorService service = null;
- public ScheduledThreadPoolDemo() {
- service = Executors.newScheduledThreadPool(2);
- }
- void testScheduleWork() {
- Date current = new Date();
- System.out.println("***************testScheduleWork************
- ***");
- // schedule by delay
- Date date = new Date();
- date.setTime(current.getTime()+TimeUnit.MILLISECONDS.convert(
- 10, TimeUnit.SECONDS));
- service.schedule(new Work(1, date), 10, TimeUnit.SECONDS);
- // schedule by date
- Date date2 = new Date();
- date2.setTime(current.getTime()+TimeUnit.MILLISECONDS.convert(
- 5, TimeUnit.SECONDS));
- service.schedule(new Work(2, date2), date2.getTime()-current.
- getTime(), TimeUnit.MILLISECONDS);
- }
- void testScheduleOutdatedWork() {
- System.out.println("***************testScheduleOutdatedWork****
- ***********");
- Date current = new Date();
- Date date = new Date();
- // schedule by delay
- date.setTime(current.getTime()+TimeUnit.MILLISECONDS.convert(-
- 10, TimeUnit.SECONDS));
- service.schedule(new Work(1, date), date.getTime()-current.
- getTime(), TimeUnit.MILLISECONDS);
- }
- void testScheduleMultiWork() {
- System.out.println("***************testScheduleMultiWork*******
- ********");
- for (int i = 0; i < 5; i++) {
- Date date = new Date();
- long offset = (long)(Math.random()*10) - 5;
- date.setTime(date.getTime()+TimeUnit.MILLISECONDS.convert(
- offset, TimeUnit.SECONDS));
- System.out.println(date);
- service.schedule(new Work(i, date), date.getTime()-new
- Date().getTime(), TimeUnit.MILLISECONDS);
- }
- }
- class Work implements Runnable {
- private int id;
- private Date date;
- public Work (int id, Date date) {
- this.id = id;
- this.date = date;
- }
- public void run() {
- System.out.println(Thread.currentThread().getName() + "
- Begins Work " + id);
- System.out.println("Work " + id + " Scheduled Time: " +
- date.toString());
- System.out.println("Work " + id + " Start Time: " + new
- Date().toString());
- try {
- Thread.sleep(5000);
- }
- catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- System.out.println("Work " + id + " End Time: " + new Date(
- ).toString());
- System.out.println(Thread.currentThread().getName() + "
- Ends Work " + id);
- }
- }
- }
在 testScheduleOutdatedWork 裡我們測試了如果 delay 是負的或 date 已過期的狀況,
結果會馬上執行補做喔,而不是就不做了!
像下面的結果程式開始的時間是 21:17:09,排程的時間是20秒前的 21:16:59,
所以程式一執行他馬上就補做了!
***************testScheduleOutdatedWork*************** pool-1-thread-1 Begins Work 1 Work 1 Scheduled Time: Wed Nov 07 21:16:59 CST 2012 Work 1 Start Time: Wed Nov 07 21:17:09 CST 2012 Work 1 End Time: Wed Nov 07 21:17:14 CST 2012 pool-1-thread-1 Ends Work 1
最後在 testScheduleMultiWork 裡我們是要測試 Thread Pool 的效果,
仔細觀察可以發現奇妙的結果喔!
程式在 21:28:43 開始後馬上補做 28:38, 28:39 兩個過期的工作,
而在工作執行期間 44, 45兩個工作也應該要馬上做了,
但因為 Pool 中只有兩條 Thread,所以這兩項工作被 delay,要等前面的工作做完才做。
同理我們看到最後執行的 Work 3,排程的時間是 47,但開始執行時已經是 53囉!
***************testScheduleMultiWork*************** Wed Nov 07 21:28:44 CST 2012 Wed Nov 07 21:28:45 CST 2012 Wed Nov 07 21:28:39 CST 2012 Wed Nov 07 21:28:47 CST 2012 Wed Nov 07 21:28:38 CST 2012 pool-1-thread-2 Begins Work 2 pool-1-thread-1 Begins Work 4 Work 2 Scheduled Time: Wed Nov 07 21:28:39 CST 2012 Work 4 Scheduled Time: Wed Nov 07 21:28:38 CST 2012 Work 2 Start Time: Wed Nov 07 21:28:43 CST 2012 Work 4 Start Time: Wed Nov 07 21:28:43 CST 2012 Work 2 End Time: Wed Nov 07 21:28:48 CST 2012 Work 4 End Time: Wed Nov 07 21:28:48 CST 2012 pool-1-thread-2 Ends Work 2 pool-1-thread-1 Ends Work 4 pool-1-thread-1 Begins Work 0 pool-1-thread-2 Begins Work 1 Work 0 Scheduled Time: Wed Nov 07 21:28:44 CST 2012 Work 1 Scheduled Time: Wed Nov 07 21:28:45 CST 2012 Work 0 Start Time: Wed Nov 07 21:28:48 CST 2012 Work 1 Start Time: Wed Nov 07 21:28:48 CST 2012 Work 0 End Time: Wed Nov 07 21:28:53 CST 2012 Work 1 End Time: Wed Nov 07 21:28:53 CST 2012 pool-1-thread-1 Ends Work 0 pool-1-thread-2 Ends Work 1 pool-1-thread-1 Begins Work 3 Work 3 Scheduled Time: Wed Nov 07 21:28:47 CST 2012 Work 3 Start Time: Wed Nov 07 21:28:53 CST 2012 Work 3 End Time: Wed Nov 07 21:28:58 CST 2012 pool-1-thread-1 Ends Work 3
service = Executors.newScheduledThreadPool(2); // 只要有空的 Thread 就直接執行 service.execute(command); // 固定週期,如:initialDelay, initialDelay+period, initialDelay+2*period …… // 下一個工作開始時間以前一工作開始時間加上 period 計算 service.scheduleAtFixedRate(command, initialDelay, period, unit); // 固定延遲, 下一個工作開始時間以前一工作結束時間加上 delay 計算 service.scheduleWithFixedDelay(command, initialDelay, delay, unit);
若想知道更多有關 Java 時間相關的轉換、排程等應用,
或是想看其他我所寫關於 Java 的範例程式,請見:Java 教學及程式範例大全
關鍵字:Java, Thread, Pool, Executor, Executors, ThreadExecutor, ThreadPoolExecutor, ScheduledThreadPool, execute, scheduleAtFixedRate, scheduleWithFixedDelay, schedule
參考資料: