
一. 為什么需要多執行緒
這個問題是給基礎不扎實的人提的;
原因一首先提一下QPS計算公式(并發數/回應時間(s)),使用多執行緒就是提升并發數,換句話說就是為了提升QPS;那么多執行緒越多是不是QPS就越高性能就越好呢?當然不是,分子雖然提高了,但是分母也增大了;多執行緒的使用會在CPU上開辟一個時間片,會增加背景關系切換的耗時;因此多執行緒也不是越多越好,
原因二大部分專案當中如果使用單執行緒,那么從一個請求進來到回應,只有協議決議和回應后資料處理占用了CPU(先不考慮計算型服務),那么請求發送到服務后,CPU一直處于閑置狀態,等待IO/磁盤處理結束;引入多執行緒后,當程式處理IO時可以要CPU處理其他的事情,等到當前執行緒需要CPU時再切換回來處理;因此多執行緒能充分利用CPU來提升性能;這里細心的朋友應該還發現了多執行緒的一個特點,多執行緒并不是真正的并發一起執行,而是不同時間片來回切換來執行不同任務,只是cpu處理的效率很快,給人的感覺是同時在執行
二. 如果使用執行緒池,執行緒池的執行緒數怎么設定
關于執行緒池執行緒數的設定應該很多地方都有介紹,我相信大家只是看了個結果,不知道原理;我這里就詳細介紹一下.
首先提幾個關鍵詞,cpu核數、IO密集型服務、計算型密集型服務、阻塞系數=阻塞時間/(阻塞時間+計算時間);
阻塞這里是針對IO來說的,所以阻塞時間就是IO耗時;計算時間級CPU耗時;
然后我再舉一個例子,假如一個服務中,阻塞時間50毫秒,計算時間10毫秒,即cpu有50毫秒的時間處于閑置;是不是在這期間cpu可以處理5個這樣的請求;再加上第一個請求總共就是處理6個請求,
那么我再提出公式
執行緒數= ncpu/(1-阻塞系數)
然后把上面的50、10帶入進去計算,如果是單核是不是就是6,那么四核就可以設定大概24個執行緒
上面公式也可以等效成:執行緒數=ncpu*(1+阻塞時間/計算時間);
看到這里大家應該看懂了怎么計算執行緒數,可能會提出疑問,為什么網上看到的計算型密集服務的執行緒數公式=ncpu+1(大家先忽略公式)比IO型服務的設定的執行緒數要偏少很多呢;那是因為之所以叫計算型服務是因為服務本身大部分都是在計算,而計算是影響CPU的時間,所以一個服務進來幾乎都是計算(CPU)耗時,那么大家根據這個特性把上面的阻塞時間改成0,計算時間改成50,帶入第一個公式,求出來的話1核就是一個執行緒數,ncpu+1又是什么道理呢?為什么要+1?帶入現實情況中考慮,計算型的服務不可能全部是計算,總會有一部分IO耗時,這個是毋庸置疑的,然后把引數在改一下,IO耗時10,計算耗時50,那么這就對應的上了;所以執行緒數= ncpu/(1-阻塞系數)這個公式是通用的;同時也得出另一個結論,阻塞系數越大,執行緒數設定的可以越多,反則設定越少
三. CPU的利用率是怎么計算的,怎么防止CPU過高導致程式奔潰
CPU的使用率=CPU計算時間/CPU計算時間+CPU閑置時間;因此如果CPU計算時間100毫米,閑置時間900毫米,那么利用率就是10%,如果計算時間500毫米,閑置時間0毫米,那么利用率就是100%(系統是統計單位時間內的值);所以隨著CPU的不斷計算,CPU率也是不斷變化的,
CPU過高的話,首先要定位是什么導致的,盲目開辟新的執行緒,還是程式計算過于復雜,還是不巧當的回圈或者死回圈;盲目開執行緒可以用執行緒池解決,后面這兩種就是優化程式了,如果無法優化了,可以使用sleep(0)、sleep(1)這種來解決;可能有人會問sleep(0)這有什么意義,他能優化CPU?當然可以,他雖然是讓cpu休眠0毫秒,但是還有一個作用就是會觸發cpu時間片的競爭(重新選舉),所以就不會出現一個時間片獨占整個cpu,導致cpu瞬間飆高;
既然說到這了我就再提一個問題,sleep() 和yield()有什么區別?
- 執行sleep()后觸發所有時間片一起選舉,每個時間片都可能拿到下一次運行權,yield()指揮把執行權交給優先級相同或者更高的
- 執行緒執行 sleep() 進入阻塞狀態,執行yield() 方法進入就緒狀態
- sleep() 宣告拋出 InterruptedException;yield() 方法沒有宣告拋出例外
- sleep() 有時間阻塞時間引數;yield() 無引數(直接讓出 CPU 的執行權時間由 JVM 控制)
一個個字手敲的,麻煩大家給個贊支持下,謝謝!如有不同意見歡迎評論;
轉載請注明出處,原創不易!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/171567.html
標籤:其他
