轉自: https://www.cnblogs.com/dennyzhangdd/p/6909771.html?utm_source=itdadao&utm_medium=referralhtml
正文算法
關於如何計算併發線程數,通常分兩派,來自兩本書,且都是好書,到底哪一個是對的?問題追蹤後,整理以下:數據庫
第一派:《Java Concurrency in Practice》即《java併發編程實踐》,以下圖:編程
如上圖,在《Java Concurrency in Practice》一書中,給出了估算線程池大小的公式:swift
Nthreads=Ncpu*Ucpu*(1+w/c),其中服務器
Ncpu=CPU核心數網絡
Ucpu=cpu使用率,0~1多線程
W/C=等待時間與計算時間的比率併發
第二派:《Programming Concurrency on the JVM Mastering》即《Java 虛擬機併發編程》
線程數=Ncpu/(1-阻塞係數)
對於派系一,假設cpu100%運轉,即撇開CPU使用率這個因素,線程數=Ncpu*(1+w/c)。
如今假設將派系二的公式等於派系一公式,即Ncpu/(1-阻塞係數)=Ncpu*(1+w/c),===》阻塞係數=w/(w+c),即阻塞係數=阻塞時間/(阻塞時間+計算時間),這個結論在派系二後續中獲得應徵,以下圖:
因而可知,派系一和派系二實際上是一個公式......這樣我就放心了......
那麼實際使用中併發線程數如何設置呢?分析以下(咱們以派系一公式爲例):
Nthreads=Ncpu*(1+w/c)
IO密集型:通常狀況下,若是存在IO,那麼確定w/c>1(阻塞耗時通常都是計算耗時的不少倍),可是須要考慮系統內存有限(每開啓一個線程都須要內存空間),這裏須要上服務器測試具體多少個線程數適合(CPU佔比、線程數、總耗時、內存消耗)。若是不想去測試,保守點取1即,Nthreads=Ncpu*(1+1)=2Ncpu。這樣設置通常都OK。
計算密集型:假設沒有等待w=0,則W/C=0. Nthreads=Ncpu。
至此結論就是:
IO密集型=2Ncpu(能夠測試後本身控制大小,2Ncpu通常沒問題)(常出現於線程中:數據庫數據交互、文件上傳下載、網絡數據傳輸等等)
計算密集型=Ncpu(常出現於線程中:複雜算法)
java中:Ncpu=Runtime.getRuntime().availableProcessors()
=========================此處可略過=============================================
固然派系一種《Java Concurrency in Practice》還有一種說法,
即對於計算密集型的任務,在擁有N個處理器的系統上,當線程池的大小爲N+1時,一般能實現最優的效率。(即便當計算密集型的線程偶爾因爲缺失故障或者其餘緣由而暫停時,這個額外的線程也能確保CPU的時鐘週期不會被浪費。)
即,計算密集型=Ncpu+1,可是這種作法致使的多一個cpu上下文切換是否值得,這裏不考慮。讀者可本身考量。
======================================================================
選擇線程池併發線程數的因素不少:任務類型、內存等線程中使用到全部資源都須要考慮。本文通過對現有文獻的分析論證,得出結論,並給出了實際應用公式,實乃工程師之福利,技術之典範......
---
轉自: http://swiftlet.net/archives/3012
在Java中,經過下面的代碼,咱們能夠很容易地獲取到系統可用的處理器核心數目:
1
|
Runtime.getRuntime().availableProcessors();
|
基本原則是:應用程序的最小線程數應該等於可用的處理器核數。具體場景又分爲如下兩種狀況:
(1)若是全部的任務都是計算密集型的,則建立處理器可用核心數那麼多個線程就能夠了。在這種狀況下,建立更多的線程對程序性能而言反而是不利的。由於當有多個任務處於就緒狀態時,處理器核心須要在線程間頻繁進行上下文切換,而這種切換對程序性能損耗較大。
(2)若是任務都是IO密集型的,那麼咱們就須要開更多的線程來提升性能。當一個任務執行IO操做時,其線程將被阻塞,因而處理器能夠當即進行上下文切換以便處理其餘就緒線程。若是咱們只有處理器可用核心數那麼多個線程的話,即便有待執行的任務也沒法處理,由於咱們已經拿不出更多的線程供處理器調度了。
總之,若是任務有50%的時間處於阻塞狀態,則程序所需線程數爲處理器可用核心數的兩倍。若是任務被阻塞的時間少於50%,即這些任務是計算密集型的,則程序所需線程數將隨之減小,但最少也不該低於處理器的核心數。若是任務被阻塞的時間大於執行時間,即該任務是IO密集型的,咱們就須要建立比處理器核心數大幾倍數量的線程。計算出程序所需線程的總數的公式以下:
線程數=CPU可用核心數/(1-阻塞係數),其中阻塞係數的取值在0和1之間。
計算密集型任務的阻塞係數爲0,而IO密集型任務的阻塞係數則接近1。一個徹底阻塞的任務是註定要掛掉的,因此咱們無須擔憂阻塞係數會達到1。