到底多少線程算是線程數太多?
(點擊
上方公眾號
,可快速關注)
來源:ImportNew - paddx
問題:
我寫了一個服務,並為每個請求分配一個線程來處理,我這樣做的原因是因為基本上每個請求都是一次資料庫的查詢操作。我使用了一個線程池的庫來減少線程的創建和銷毀。
我的問題是:像這樣的I/O多線程,什麼才是一個好的臨界點?我知道這需要一個粗略的估計值,但這個值應該是幾百呢還是幾千?
更新:
非常感謝你們所有的回答,看起來我需要去測試找出線程數上限,問題是:我怎麼知道線程數已經到達了上限?我究竟該如何去測量?
回答:
有的人可能會說,兩個線程就算是太多的線程了。我不是特別同意這種看法。
我的建議是:測試,而不是猜想。我建議把線程數設置為可配置的,並初始化為100個線程,然後運行你的軟體並對它進行監控。
如果線程的使用峰值才為3,那說明100個線程就是太多了。如果一天中的大部分時間都保持在100個線程,那就將線程的數量提高到200,然後再監視其運行情況。
你確實可以讓你的代碼自動監控線程的使用,並在下次啟動的時候自動修改配置選項,但沒必要這麼做。
詳述:
我不支持經常變動你的線程池,而是儘可能的使用某一個值,你可能會問一個線程池合適的臨界點是什麼,現假定你的線程池可以限制線程池的最大線程數(這是一件非常好的事情)。
我寫過線程池和資料庫連接池,他們擁有以下最基本的特徵(我認為這些對系統的性能來說是必要的):
最小活動線程數
最大線程數
多久關閉一個未被使用的線程
第一條是為了確保線程池的最低性能標準(這些線程是一直可以被使用的)。第二條是為了限制活動線程的資源使用。第三條是在一定的時間內將線程數返回到基準的設置,以減少資源的使用。
你需要去平衡線程未被完全使用(情況A)和沒有足夠的工作線程(情況B)的情況。
A通常指內存的使用(棧等等),因為一個不工作的線程不會佔用太多的CPU資源。B通常會延遲處理到達請求,直到有可以使用的線程。
這就是為什麼要去測算,正如你遇到的這種情況,絕大部分線程需要等待資料庫的響應才能運行。這就有兩個主要因素影響線程的數量:
第一個因素是資料庫的有效連接數。這是一個硬性的限制,除非你能通過資料庫管理系統增加資料庫的連接數。在這裡,我假設你的資料庫管理系統能夠承擔的資料庫連接數是無限制的。(雖然,理想情況下,你也應該測量一下)
其次,線程數量應該依賴於你系統的歷史運行情況。最小的線程數你應該設置為在歷史最低的線程數的基礎上加上A%和一個絕對的最小數值(例如,讓它也可被配置,就像A一樣)5。
線程池的最大數應該設置為在歷史最大線程數的基礎上加上B%。
你也應該監控你系統運行情況的變化,如果因為某些原因,在某一個非常重要的時刻,你的線程池使用率達到100%(這將影響你客戶端的性能),這就應該增加你線程池所允許的最大線程的數量,使其再增加B%。
對於「我究竟如何去測試」的回答:
你應該明確測算當前運行(例如,等待資料庫調用的返回)負載下的最大線程數量。然後增加一個安全因子,如10%(強調一下,很多人貌似把我舉得例子當做了固定的建議)
此外,在生產環境下,這點也應該是需要去調節的。在剛開始的時候先估計一個值是沒問題的,但是,你永遠也無法預料生產環境下會產生什麼情況(這就是為什麼要把所有的這些都設置為運行時可配置的原因)。這就能應付各種客戶端調用時所出現的不可預期的情況。
看完本文有收穫?請轉發分享給更多人
關注「ImportNew」,提升Java技能
※zookeeper入門系列:概述
※使用 partclone 備份磁碟分區
TAG:ImportNew |