【筆記】ThreadPoolExecutor源碼閱讀(二)
AQS在Worker中的應用
我對這個上鎖一直搞不懂,雖然有註釋說是允許中斷啥的,但是還是一頭霧水,就打算直接看代碼分析。第一眼看到這個lock的時候,我就嚇到了。啥,一上鎖,多個線程不是就要同步排隊了嘛,而且也沒這必要啊。看清楚了才知道,鎖來自於方法參數Worker,也就是說,每個線程請求的同步鎖都是各自的Worker的鎖,故不存在這些個線程競爭一個鎖的情況。那問題又來了,我自己的鎖,又沒人跟我搶,犯得著每做一個任務都上鎖嗎?
註釋不是說了嗎,允許中斷,那肯定跟中斷有關,朝這個方向去找啊。當然,我當時並沒有這樣去找,而是機緣巧合,看到ThreadPoolExecutor其他代碼的時候突然意識到的。
我先看到了shutdown方法,發現有中斷空閑Worker的方法。但是在此之前,我並不知道線程池是如何區別Worker空閑和忙碌的,只知道線程池有workers字段用來存儲創建的Worker。於是,我就順著方法查看下去。找到關閉空閑Worker方法的實現。
由上述代碼可知,線程池區分Worker是否空閑的方法就是,能否成功獲取到Worker的鎖。這個鎖是獨占鎖,由前面的代碼可知,一旦Worker對應線程獲取到任務,就會上鎖並開始執行。那這樣,w.tryLock()方法將失敗,此線程就會被判定為是非空閑線程。而如果線程在獲取任務的過程中被阻塞,也就是還沒調用w.lock(),那這裏的tryLock()將成功獲取獨占鎖,那此線程就被判定為是空閑線程而被中斷。
註:shutdown()方法的語義就是,讓已經開始的任務繼續做,未開始的終止,把多余的工作線程關閉。其對應的狀態是SHUTDOWN
那問題又來了,如何終止已經開始的任務呢?
這裏終止已經開始的任務,就是shutdownNow方法要做的。(shutdownNow就是停止所有任務,已經開始也要停止。其對應的狀態是STOP)
前面由於無法獲取到Worker的鎖,故無法通過interruptIdleWorkers方法將其中斷。但是ThreadPoolExecutor還提供了interruptWorkers方法,該方法不用獲取鎖,直接調用Worker的interruptIfstarted方法中斷線程。
【筆記】ThreadPoolExecutor源碼閱讀(二)