Java線程池淺談

今天來談一談Java線程池如何「歸還」線程,你們都知道數據庫鏈接池使用完成後須要將鏈接還回鏈接池。Java線程池中的線程使用完後需不須要歸還,如何歸還呢,想了半天沒想明白,看了JDK源代碼後搞明白了。數據庫

核心代碼都在ThreadPoolExecutor類裏。oop

首先建立線程池時,設置corePoolSize、maximumPoolSize。意思很明白,很少解釋。ui

而後當調用線程池的execute方法時,若是當前線程池裏的線程數比corePoolSize小,則直接建立一個新的線程,這個地方有個巧妙的處理,並非直接new Thread,而是建立一個Worker對象。this

Worker類實現了Runnable接口,以下圖所示:spa

private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable

並持有一個Thread對象,該Thread對象包裝了Worker的Runnable接口,以下圖所示:線程

Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    this.thread = getThreadFactory().newThread(this);
}

Worker的run方法以下:對象

/** Delegates main run loop to outer runWorker  */
public void run() {
    runWorker(this);
}
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

Worker的run方法執行時會從一個隊列裏獲取Runnable接口的實現,即上圖的getTask方法,獲取到後執行task的run方法。接口

核心部分都已經展現完了,讓咱們把他們串聯起來。隊列

線程池的execute方法執行時建立一個Worker,而後執行Worker持有的線程的start方法,其實也就是啓動了一個線程。該線程執行Worker的run方法,由於Worker也實現了Runnable接口。run執行時首先從隊列獲取任務,有的話就執行其run方法,不是start方法,因此並無新啓動線程。該線程執行完成後,若是隊列中有任務,那麼該線程會繼續執行新的任務,實現了線程複用。get

因此線程池裏的線程並不須要顯式歸還。

相關文章
相關標籤/搜索