2017年3月8日 星期三

ExecutorService (Thread 六)

連線到資料庫有個連線池,Thread 也有 Thread pool ,ExecutorService 就是個 Thread pool


※取得ExecutorService

以下是overloading,以下只列出同名的其中一個方法


ExecutorService s1 = Executors.newCachedThreadPool();// 可快取的 Thread,預設idle 60 秒
ExecutorService s2 = Executors.newFixedThreadPool(3);// 固定數量的 Thread
ExecutorService s3 = Executors.newSingleThreadExecutor();// 單一的 Thread
    
ScheduledExecutorService sch1 = Executors.newScheduledThreadPool(3);// 可排程的 Thread
ScheduledExecutorService sch2 = Executors.newSingleThreadScheduledExecutor();// 單一可排程的

※最後兩個可排程,但要用 ScheduledExecutorService 去接

※Executors.newFixedThreadPool(1) 等於 Executors.newSingleThreadExecutor(),看原始碼就知道,排程的也是一樣



※ScheduledExecutorService

ScheduledExecutorService 有4個方法
delay配合TimeUnit的時間間隔,是設定時間用的

delay:多少時間後開始執行
<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)

以下兩個不容易分
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
initialDelay:多少時間後開始執行,只有第一次
period、delay:第二次(含)之後看的是這個時間
period、delay不同的是
period:command 的開始時間開始算,算到 period 設定的時間為一個間隔,如果設定5秒就每5秒執行一次
delay:command 的結束時間開始算,算到 delay 設定的時間為一個間隔,如果設定5秒就每5秒加上 command 執行的時間執行一次

※排程範例

ScheduledExecutorService sch1 = Executors.newScheduledThreadPool(1);
ScheduledExecutorService sch2 = Executors.newSingleThreadScheduledExecutor();
    
ScheduledFuture<String> future1 = sch1.schedule(new Callable<String>() {
    public String call() throws Exception {
        return "xxx";
    }
}, 3, TimeUnit.SECONDS);
    
try {
    System.out.println(future1.get());
    sch1.shutdown();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
    
ScheduledFuture<?> future2 = sch2.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("哇哈哈");
    }
}, 1, 1, TimeUnit.SECONDS);
    
try {
    future2.get();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

※注意 future2 的順序,以上面的例子是先執行3秒後的xxx,然後再執行哇哈哈
如果將 future2 放到 future1 的下面,然後在 future1.get() 下增加 future2.get(),最下面的 future2.get() 刪除,此時結果會是1秒的哇哈哈先執行



※Future 的 cancel 方法

參數是布林值,表示如果任務正在執行,是否要取消
回傳是否成功取消,如果為false,通常已經正常完成


ScheduledExecutorService sch = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> future = sch.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("哇哈哈");
    }
}, 1, 1, TimeUnit.SECONDS);
    
ScheduledFuture<?> f = sch.schedule(new Callable<Boolean>() {
    public Boolean call() throws Exception {
        return future.cancel(true);
    }
}, 5, TimeUnit.SECONDS);
    
try {
    // System.out.println(future.get());
    System.out.println("是否取消=" + f.get());
    sch.shutdown();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

※註解打開會出「java.util.concurrent.CancellationException」的錯


沒有留言:

張貼留言