多執行緒技術原理
阿新 • • 發佈:2019-01-08
首先是其繼承關係如下:
通過觀察上面四種執行緒池的原始碼:
如:newFixedThreadPool
- publicstatic ExecutorService newFixedThreadPool(int nThreads) {
- returnnew ThreadPoolExecutor(nThreads, nThreads,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>());
- }
- publicstatic ExecutorService newCachedThreadPool() {
- returnnew ThreadPoolExecutor(0, Integer.MAX_VALUE,
- 60L, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>());
- }
- public
- returnnew FinalizableDelegatedExecutorService
- (new ThreadPoolExecutor(1, 1,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>()));
- }
可以發現,其實它們呼叫的都是同一個介面ThreadPoolExecutor方法,只不過傳入引數不一樣而已。下面就來看看這個神祕的ThreadPoolExecutor。
首先來看看它的一些基本引數:
- publicclass ThreadPoolExecutor extends AbstractExecutorService {
- //執行狀態標誌位
- volatileint runState;
- staticfinalint RUNNING = 0;
- staticfinalint SHUTDOWN = 1;
- staticfinalint STOP = 2;
- staticfinalint TERMINATED = 3;
- //執行緒緩衝佇列,當執行緒池執行緒執行超過一定執行緒時並滿足一定的條件,待執行的執行緒會放入到這個佇列
- privatefinal BlockingQueue<Runnable> workQueue;
- //重入鎖,更新核心執行緒池大小、最大執行緒池大小時要加鎖
- privatefinal ReentrantLock mainLock = new ReentrantLock();
- //重入鎖狀態
- privatefinal Condition termination = mainLock.newCondition();
- //工作都set集合
- privatefinal HashSet<Worker> workers = new HashSet<Worker>();
- //執行緒執行完成後線上程池中的快取時間
- privatevolatilelong keepAliveTime;
- //核心執行緒池大小
- privatevolatileint corePoolSize;
- //最大執行緒池大小
- privatevolatileint maximumPoolSize;
- //當前執行緒池在執行執行緒大小
- privatevolatileint poolSize;
- //當緩衝佇列也放不下執行緒時的拒絕策略
- privatevolatile RejectedExecutionHandler handler;
- //執行緒工廠,用來建立執行緒
- privatevolatile ThreadFactory threadFactory;
- //用來記錄執行緒池中曾經出現過的最大執行緒數
- privateint largestPoolSize;
- //用來記錄已經執行完畢的任務個數
- privatelong completedTaskCount;
- ................
- }
初始化執行緒池大小 有以下四種方法:
從原始碼中可以看到其實最終都是呼叫了以下的方法:
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- ThreadFactory threadFactory,
- RejectedExecutionHandler handler) {
- if (corePoolSize < 0 ||
- maximumPoolSize <= 0 ||
- maximumPoolSize < corePoolSize ||
- keepAliveTime < 0)
- thrownew IllegalArgumentException();
- if (workQueue == null || threadFactory == null || handler == null)
- thrownew NullPointerException();
- this.corePoolSize = corePoolSize;
- this.maximumPoolSize = maximumPoolSize;
- this.workQueue = workQueue;
- this.keepAliveTime = unit.toNanos(keepAliveTime);
- this.threadFactory = threadFactory;
- this.handler = handler;
- }
接下來我們來看看最重要的方法execute,其原始碼如下:
- publicvoid execute(Runnable command) {
- if (command == null)
- thrownew NullPointerException();
- if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { // 判斷1
- if (runState == RUNNING && workQueue.offer(command)) { // 判斷2
- if (runState != RUNNING || poolSize == 0) // 判斷3
- ensureQueuedTaskHandled(command);
- }
- elseif