亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

背景

Tomcat 源碼中多處用了JAVA.util.concurrent 包中的類,用以處理多線程環(huán)境下的流程控制。近日分析了下NioEndpoint 源碼,本文將以此類為背景,膜拜下 Java 大神們使用 CountDownLatch 并發(fā)控制的手法,其實(shí)也就是簡單的實(shí)際應(yīng)用,算不上高深。

類圖框架

NIO tailored thread pool, providing the following services:
Socket acceptor thread:Acceptor
Socket poller thread:Poller
Worker threads pool:Executor

以上是該類的注釋,結(jié)合源碼我們知道 NioEndpoint 就是一個(gè)定制線程池,管理了三種線程:Acceptor、Poller、Worker。
(百來的一張很清晰的結(jié)構(gòu)圖如下:)

看Tomcat如何用CountDownLatch停止容器

 

初始化

NioEndpoint 類維護(hù)了一個(gè) stopLatch 的變量,其類型就是 CountDownLatch。它根據(jù) Poller 線程的個(gè)數(shù)進(jìn)行初始化的,源碼如下:

public void bind() throws Exception {
	....
	if (acceptorThreadCount == 0) {
            // FIXME: Doesn't seem to work that well with multiple accept threads
            acceptorThreadCount = 1;
        }
        if (pollerThreadCount <= 0) {
            //minimum one poller thread
            pollerThreadCount = 1;
        }
        stopLatch = new CountDownLatch(pollerThreadCount);
	....
}

NioEndpont 類初始化時(shí)指定了 Poller 和 Accetpor 線程數(shù),而且從上面代碼的注釋信息來看 acceptorThreadCount 的固定 是 1,即 Tomcat 的 NIO 并不支持多個(gè) Accepor 線程,此外也沒有可以修改該屬性的途徑。

stopLatch 控制流程

stopLatch,顧名思義,是控制 Tomcat 的組件停止時(shí)使用的鎖,利用 CountDownLatch ,主線程等待一組線程到達(dá)某個(gè)狀態(tài)后,才進(jìn)行后面的處理。NioEndpoint 的 stopInternal() 方法的流程如下:

public void stopInternal() {
        releaseConnectionLatch();
        if (!paused) {
            pause();
        }
        if (running) {
            running = false;
            unlockAccept();
            for (int i=0; pollers!=null && i<pollers.length; i++) {
                if (pollers[i]==null) continue;
                pollers[i].destroy();
                pollers[i] = null;
            }
            try {
                stopLatch.await(selectorTimeout + 100, TimeUnit.MILLISECONDS);
            } catch (InterruptedException ignore) {
            }
            shutdownExecutor();
            eventCache.clear();
            nioChannels.clear();
            processorCache.clear();
        }
 }

該方法將導(dǎo)致所有的處理線程都停止工作,其流程為:

  1. 首先,通知Poller線程停止工作,調(diào)用其 destroy,設(shè)置 Poller 的 close 標(biāo)識(shí)為 true。
  2. 其次,設(shè)置 running 為 false,通知 Acceptor 線程終止 run 方法的循環(huán)處理。
  3. 第三,當(dāng)前線程 stopLatch.await ,等待所有的 Poller 線程的 run方法結(jié)束。Poller 的 run 方法最后一句是 stopLatch.countDown(),當(dāng) stopInternal 的 await 方法被喚醒時(shí),說明所有的Poller 線程都結(jié)束了。
  4. 第四,此處調(diào)用 await 操作的超時(shí)時(shí)間設(shè)置為 selectorTimeout,這個(gè)值也是Poller處理時(shí)的阻塞時(shí)間,也就是說:如果Poller的在輪詢過程中調(diào)用了selector.select(selectorTimeout);的話,最多等待這么長時(shí)間,就能保證所有的Poller都及時(shí)結(jié)束了。

此處,之所以不用考慮 Acceptor 的結(jié)束問題,是因?yàn)?Acceptor 線程只有一個(gè),而且它沒有阻塞處理,所以一旦 running 標(biāo)識(shí)為 false,它就會(huì)立即結(jié)束。

所有的處理線程都結(jié)束之后,shutdownExecutor() 操作會(huì)關(guān)閉工作線程池的調(diào)度器,至此,所有的線程都被關(guān)閉了。

啟示錄

開發(fā)中,如何需要自定義線程池框架,就可以參照這個(gè)流程對(duì)線程池資源進(jìn)行關(guān)閉,用 JUC 包中的并發(fā)工具類,比自己寫同步計(jì)數(shù)器方便多了!Tomcat 教我們的這一招,你學(xué)會(huì)了嗎?

分享到:
標(biāo)簽:Tomcat
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定