java中的線程池是通過Executor框架實現(xiàn)的搀突,Executor 框架包括類:Executor,Executors领迈,ExecutorService,ThreadPoolExecutor 留凭,Callable和Future、FutureTask的使用等赌莺。
線程池的框架圖冰抢,如下:
Executor: 所有線程池的接口,只有一個方法。
public interface Executor {
void execute(Runnable command);
}
ExecutorService: 增加Executor的行為艘狭,是Executor實現(xiàn)類的最直接接口挎扰。
public interface ExecutorService extends Executor {
void shutdown();
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;
}
AbstractExecutorService:是一個抽象類翠订,它實現(xiàn)了ExecutorService接口。
public abstract class AbstractExecutorService implements ExecutorService {
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { };
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { };
public Future<?> submit(Runnable task) {};
public <T> Future<T> submit(Runnable task, T result) { };
public <T> Future<T> submit(Callable<T> task) { };
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
};
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
};
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
};
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
};
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
};
}
Executors: 提供了一系列工廠方法用于創(chuàng)先線程池遵倦,返回的線程池都實現(xiàn)了ExecutorService 接口尽超。詳細了解
ThreadPoolExecutor:線程池的具體實現(xiàn)類,一般用的各種線程池都是基于這個類實現(xiàn)的。ThreadPoolExecutor繼承了AbstractExecutorService梧躺。詳細了解
構(gòu)造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize:線程池的核心線程數(shù),線程池中運行的線程數(shù)也永遠不會超過 corePoolSize 個,默認情況下可以一直存活似谁。可以通過設(shè)置allowCoreThreadTimeOut為True,此時 核心線程數(shù)就是0,此時keepAliveTime控制所有線程的超時時間掠哥。
maximumPoolSize:線程池允許的最大線程數(shù);
keepAliveTime: 指的是空閑線程結(jié)束的超時時間;
unit :是一個枚舉巩踏,表示 keepAliveTime 的單位;
workQueue:表示存放任務(wù)的BlockingQueue<Runnable隊列。
線程池的工作過程如下:
- 線程池剛創(chuàng)建時续搀,里面沒有一個線程塞琼。任務(wù)隊列是作為參數(shù)傳進來的。不過禁舷,就算隊列里面有任務(wù)彪杉,線程池也不會馬上執(zhí)行它們。
- 當(dāng)調(diào)用 execute() 方法添加一個任務(wù)時牵咙,線程池會做如下判斷:
- 如果正在運行的線程數(shù)量小于 corePoolSize派近,那么馬上創(chuàng)建線程運行這個任務(wù);
- 如果正在運行的線程數(shù)量大于或等于 corePoolSize洁桌,那么將這個任務(wù)放入隊列渴丸;
- 如果這時候隊列滿了,而且正在運行的線程數(shù)量小于 maximumPoolSize另凌,那么還是要創(chuàng)建非核心線程立刻運行這個任務(wù)曙强;
- 如果隊列滿了,而且正在運行的線程數(shù)量大于或等于 maximumPoolSize途茫,那么線程池會拋出異常RejectExecutionException。
- 當(dāng)一個線程完成任務(wù)時溪食,它會從隊列中取下一個任務(wù)來執(zhí)行囊卜。
- 當(dāng)一個線程無事可做,超過一定的時間(keepAliveTime)時错沃,線程池會判斷栅组,如果當(dāng)前運行的線程數(shù)大于 corePoolSize,那么這個線程就被停掉枢析。所以線程池的所有任務(wù)完成后玉掸,它最終會收縮到 corePoolSize 的大小。
線程池最常用的提交任務(wù)的方法有兩種:
execute:
ExecutorService.execute(Runnable runable)醒叁;
submit:
FutureTask task = ExecutorService.submit(Runnable runnable);
FutureTask<T> task = ExecutorService.submit(Runnable runnable,T Result);
FutureTask<T> task = ExecutorService.submit(Callable<T> callable);
submit(Callable callable)的實現(xiàn)司浪,submit(Runnable runnable)同理泊业。
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
FutureTask<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
可以看出submit開啟的是有返回結(jié)果的任務(wù),會返回一個FutureTask對象啊易,這樣就能通過get()方法得到結(jié)果吁伺。submit最終調(diào)用的也是execute(Runnable runable),submit只是將Callable對象或Runnable封裝成一個FutureTask對象租谈,因為FutureTask是個Runnable篮奄,所以可以在execute中執(zhí)行。關(guān)于Callable對象和Runnable怎么封裝成FutureTask對象割去,見Callable和Future窟却、FutureTask的使用。