Basic Pool
在Java中,thread pool都會實作一個介面Executor,事實上更明確的說是實作ExecutorService這個介面。前者只定義了一個簡單的execute
method,就跟我前面一個章節的execute
定義一模一樣,就是在thread pool中執行一個task。
public interface Executor {
void execute(Runnable command);
}
後者繼承了Exectuor介面,定義了更多的method,
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Methods | Description |
---|---|
submit | 可以呼叫沒有回傳值的task(Runnable)跟有回傳值的task(Callable),並且會回傳一個Future。這個Future的概念容我稍後介紹。 |
invokeAll | 一次執行多個task,並且取得所有task的future objects |
invokeAny | 一次執行多個task,並且取得第一個完成的task的future object |
shutdown shutdownNow |
讓整個thread pool的threads都停止,簡單講就是打烊了。 |
awaitTermination | 等待所有shutdown後的task都執行完成。可以說是打烊並且所有善後都處理完了。 |
另外還有一種較特殊的thread pool稱為ScheduledExecutorService。他除了可以做原本submit task到thread pool以外,還可以讓這個task不會立刻執行。他的定義如下:
public interface ScheduledExecutorService extends ExecutorService {
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
Methods | Description |
---|---|
schedule | 讓task可以在一段時間之後才執行。 |
scheduleAtFixedRate | 除了可以讓task在一段時間之後才執行之外,還可以固定週期執行 |
在看完thread pool的抽象定義之後,我們來看看有哪些現成的實作可以拿來使用。
Executors
在Java中,大部分的thread pool都是透過Executors來產生,裡面有非常多的factory method來去產生不同類型的thread pool。
Name | Description |
---|---|
Executors.newSingleThreadPool() Executors.newSingleThreadScheduledExecutor() |
產生一個只有一個thread的thread pool。 |
Executors.newFixedThreadPool(int nThreads) | 產生固定thread數量的thread pool |
Executors.newCachedThreadPool() | 產生沒有數量上限的thread pool。Thread的數量會根據使用狀況動態的增加或是減少。 |
Executors.newScheduledThreadPool(int corePoolSize) | 產生固定數量可以做scheduling的thread pool。 |
Executors.newWorkStealingPool() | 產生work stealing的thread pool,這種類型的thread pool下一章會介紹。 |
基本上大部分的情況之下,我們已經不會自己產生thread了,透過thread pool的方式可以更有效的管理我們的threads。再想想前面的銀行取票機的例子,也許一個銀行需要一般業務的取票機,另外有一個外匯的取票機,還有可能一個專屬於VIP的取票機。根據不同的業務需求,我們用不同的thread pool去管理。可以避免較為重要的工作,反而被一些比較不重要但是做比較久的task卡住。在我們的multi thread的環境之下,我們也會有類似的情境。
接下來我們介紹一個比較特別的pool,稱之為ForkJoinPool。