注冊用戶即可下載全站資源 關注Java幫幫微信公眾號
 

從構建分布式秒殺系統聊聊Threadpool線程池

4
發表時間:2018-11-08 11:55來源:Java幫幫-微信公眾號


前言

日本韩国三级aⅴ在线观看從0到1構建分布式秒殺系統案例的代碼已經全部上傳至碼云,文章也被分發到各個平臺。其中也收到了不少小伙伴喜歡和反饋,有網友如是說:

日本韩国三级aⅴ在线观看說實話,能用上的不多,中小企業都不可能用到,大型企業也不是一個人就能搞起的,大部分人一輩子都用不上,等有這個需要再搞吧。

我的觀點是贊同但不支持,基本上任何事物都是呈金字塔分布,互聯網也不例外,也就是說大部分可能都是普通人,接觸不到所謂大廠的應用場景。但是,書到用時方恨少,機會總是留給有準備的人的,除非有錢難買我樂意,只能說大千世界,每個人都有自己的生活方式,尊重并活著。

進程和線程

前面都是扯淡,也不是什么鋪墊,在聊線程池之前我們最好簡單了解下什么是進程,什么是線程,進程和線程到底有什么區別?

日本韩国三级aⅴ在线观看這里我們,搬運下某百科的釋義:

進程是計算機中的程序關于某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體。

當然,知乎上也有不少網友的回答,每個人都有自己不同的理解方式。這里我們拿Tomcat容器做例子:你可以這么理解,運行中的Tomcat容器就是一個進程,而每個用戶的操作(查詢、上傳)可以當做一個或者多個線程。

線程池

日本韩国三级aⅴ在线观看秒殺活動中,瞬時并發是非常大的,如果每一個請求都開啟一個新線程,系統就要不斷的進行線程的創建和銷毀,有時花在創建和銷毀線程上的時間會比線程真正執行的時間還長。并且由于硬件條件限制,線程數量又不能無限創建。

那么線程池到底解決了那些問題:

  • 降低資源消耗:通過重用已經創建的線程來降低線程創建和銷毀的消耗

  • 提高響應速度:任務到達時不需要等待線程創建就可以立即執行

  • 日本韩国三级aⅴ在线观看提高線程的可管理性:線程池可以統一管理、分配、調優和監控


執行流程
  • 調用ThreadPoolExecutor的execute提交線程,首先檢查CorePool,如果CorePool內的線程小于CorePoolSize,新創建線程執行任務。

  • 日本韩国三级aⅴ在线观看如果當前CorePool內的線程大于等于CorePoolSize,那么將線程加入到BlockingQueue。

  • 日本韩国三级aⅴ在线观看如果不能加入BlockingQueue,在小于MaxPoolSize的情況下創建線程執行任務。

  • 日本韩国三级aⅴ在线观看如果線程數大于等于MaxPoolSize,那么執行拒絕策略。

模擬測試

為了方便測試,我們在Control中定義了線程池,來模擬用戶秒殺動作:

定義初始線程數:

privatestaticint corePoolSize = Runtime.getRuntime().availableProcessors();
  • IO密集型任務 = 一般為2*CPU核心數(常出現于線程中:數據庫數據交互、文件上傳下載、網絡數據傳輸等等)

  • CPU密集型任務 = 一般為CPU核心數+1(常出現于線程中:復雜算法)

  • 日本韩国三级aⅴ在线观看混合型任務 = 視機器配置和復雜度自測而定

定義Executor:

privatestatic ThreadPoolExecutor executor  = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1000));
  • corePoolSize用于指定核心線程數量

  • maximumPoolSize指定最大線程數

  • keepAliveTime和TimeUnit指定線程空閑后的最大存活時間

  • workQueue則是線程池的緩沖隊列,還未執行的線程會在隊列中等待,監控隊列長度,確保隊列有界;不當的線程池大小會使得處理速度變慢,穩定性下降,并且導致內存泄露。如果配置的線程過少,則隊列會持續變大,消耗過多內存;而過多的線程又會 由于頻繁的上下文切換導致整個系統的速度變緩——殊途而同歸。隊列的長度至關重要,它必須得是有界的,這樣如果線程池不堪重負了它可以暫時拒絕掉新的請求。

  • ExecutorService 默認的實現是一個無界的LinkedBlockingQueue。

Tomcat線程池

日本韩国三级aⅴ在线观看以上只是為了測試方便,模擬出的數據。真實的生產環境,我們要接入Nginx和Tomcat來處理用戶的請求。而Tomcat作為一名容器也是有自己的一套連接池的,作為開發人員你并不需要自己去實現。

Tomcat默認使用自帶的連接池,這里我們也可以自定義實現,打開/conf/server.xml文件,在Connector之前配置一個線程池:

<Executorname="tomcatThreadPool"namePrefix="tomcatThreadPool-"maxThreads="1000"maxIdleTime="300000"minSpareThreads="200"/>
  • name:共享線程池的名字。這是Connector為了共享線程池要引用的名字,該名字必須唯一。默認值:None;

  • 日本韩国三级aⅴ在线观看namePrefix:在JVM上,每個運行線程都可以有一個name 字符串。這一屬性為線程池中每個線程的name字符串設置了一個前綴,Tomcat將把線程號追加到這一前綴的后面。默認值:tomcat-exec-;

  • maxThreads:該線程池可以容納的最大線程數。默認值:200;

  • maxIdleTime:在Tomcat關閉一個空閑線程之前,允許空閑線程持續的時間(以毫秒為單位)。只有當前活躍的線程數大于minSpareThread的值,才會關閉空閑線程。默認值:60000(一分鐘)。

  • minSpareThreads:Tomcat應該始終打開的最小不活躍線程數。默認值:25。

配置Connector:

<Connectorexecutor="tomcatThreadPool"port="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"minProcessors="5"maxProcessors="75"acceptCount="1000"/>
  • executor:表示使用該參數值對應的線程池;

  • minProcessors:服務器啟動時創建的處理請求的線程數;

  • maxProcessors:最大可以創建的處理請求的線程數;

  • 日本韩国三级aⅴ在线观看acceptCount:指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理。

思考

  • 為什么線程數最好不要太大于CPU核數?

  • 為什么Tomcat中默認線程數遠大于CPU核數?

  • 日本韩国三级aⅴ在线观看Nginx為什么要進入線程池,基于什么場景考慮?


支付寶贊助-Java幫幫社區
微信贊助-Java幫幫社區
Java幫幫公眾號生態

Java幫幫公眾號生態

總有一款適合你

Java幫幫-微信公眾號

Java幫幫-微信公眾號

將分享做到極致

Python幫幫-公眾號

Python幫幫-公眾號

人工智能,爬蟲,學習教程

大數據驛站-微信公眾號

大數據驛站-微信公眾號

一起在數據中成長

九點編程-公眾號

九點編程-公眾號

深夜九點學編程

程序員生活志-公眾號

程序員生活志-公眾號

互聯網,職場,程序員那些事兒

Java幫幫學習群生態

Java幫幫學習群生態

總有一款能幫到你

Java學習群

Java學習群

與大牛一起交流

大數據學習群

大數據學習群

在數據中成長

九點編程學習群

九點編程學習群

深夜九點學編程

python學習群

python學習群

人工智能,爬蟲

測試學習群

測試學習群

感受測試的魅力

Java幫幫生態承諾

Java幫幫生態承諾

一直堅守,不負重望

初心
勤儉
誠信
正義
分享
合作品牌 非盈利生態-優質內容分享傳播者
關于我們
友鏈申請
友鏈交換:加幫主QQ2524138991 留言即可 24小時內答復  
全站內容非商業用途,內容來源于網友,并遵循 許可,如有異議請聯系客服。
會員登錄
獲取驗證碼
登錄
登錄
我的資料
留言
回到頂部