今天來談一談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
因此線程池裏的線程並不須要顯式歸還。