為什麼要用多執行緒

2021-06-18 11:56:38 字數 1657 閱讀 2881

以前我認為多執行緒的作用就是提公升效能。實際上,多執行緒並不一定能提公升效能(甚至還會降低效能);多執行緒也不只是為了提公升效能。多執行緒主要有以下的應用場景:

1、避免阻塞(非同步呼叫)

單個執行緒中的程式,是順序執行的。如果前面的操作發生了阻塞,那麼就會影響到後面的操作。這時候可以採用多執行緒,我感覺就等於是非同步呼叫。這樣的例子有很多:

ajax呼叫,就是瀏覽器會啟乙個新的執行緒,不阻塞當前頁面的正常操作;

流程在某個環節呼叫web service,如果是同步呼叫,則需要等待web service呼叫結果,可以啟動新執行緒來呼叫,不影響主流程;

android裡,不要在ui thread裡執行耗時操作,否則容易引發anr;

建立工單時,需要級聯往其他表中插入資料,可以將級聯插入的動作放到新執行緒中,先返回工單建立的結果……

2、避免cpu空轉

以http server為例,如果只用單執行緒響應http請求,即處理完一條請求,再處理下一條請求的話,cpu會存在大量的閒置時間

因為處理一條請求,經常涉及到rpc、資料庫訪問、磁碟io等操作,這些操作的速度比cpu慢很多,而在等待這些響應的時候,cpu卻不能去處理新的請求,因此http server的效能就很差

所以很多web容器,都採用對每個請求建立新執行緒來響應的方式實現,這樣在等待請求a的io操作的等待時間裡,就可以去繼續處理請求b,對併發的響應性就好了很多

3、提公升效能

在滿足條件的前提下,多執行緒確實能提公升效能

打乙個比方,多執行緒就相當於,把要炒的菜放到了不同的鍋裡,然後用不同的爐來炒,當然速度會比較快。本來需要先炒西紅柿,10分鐘;再炒白菜10分鐘;加起來就需要20分鐘。用了多執行緒以後,分別放在2個鍋裡炒,10分鐘就都炒好了

基本上,需要滿足3個條件:

第1,任務具有併發性,也就是可以拆分成多個子任務。並不是什麼任務都能拆分的,條件還比較苛刻

子任務之間不能有先後順序的依賴,必須是允許並行的

比如

a = b + c

d = e + f

這個是可以並行的;

a = b + c

d = a + e

這個就無法並行了,第2步計算需要依賴第1步的計算結果,即使分成2個執行緒,也不會帶來任何效能提公升

另外,還不能有資源競爭。比如2個執行緒都需要寫乙個檔案,第1個執行緒將檔案鎖定了,第2個執行緒只能等著,這樣的2個子任務,也不具備併發性;執行sychronized**,也是同樣的情況

第2,只有在cpu是效能瓶頸的情況下,多執行緒才能實現提公升效能的目的。比如一段程式,瓶頸在於io操作,那麼把這個程式拆分到2個執行緒中執行,也是無法提公升效能的

第3,有點像廢話,就是需要有多核cpu才行。否則的話,雖然拆分成了多個可並行的子任務,但是沒有足夠的cpu,還是只有乙個cpu在多個執行緒中切換來切換去,不但達不到提公升效能的效果,反而由於增加了額外的開銷,而降低了效能。類似於雖然把菜放到了2個鍋裡,但是只有1個爐子一樣

如果上述條件都滿足,有乙個經驗公式可以計算效能提公升的比例,叫阿姆達爾定律:

速度提公升比例 = 1/[(1-p)+(p/n)],其中p是可並行任務的比例,n是cpu核心數量

假設cpu核心是無限的,則公式簡化為1/(1-p)

假設p達到了80%(已經非常高了),那麼速度提公升比例也只能達到5倍而已

為什麼要用多執行緒

1 避免阻塞 非同步呼叫 2 避免cpu空轉 需要處理的資訊提供得太慢,導致 cpu 效能沒有充分利用,這個時候多程序能充分利用 cpu 在io程式設計一節中,我們已經知道,cpu的速度遠遠快於磁碟 網路等io。在乙個執行緒中,cpu執行 的速度極快,然而,一旦遇到io操作,如讀寫檔案 傳送網路資料...

Java為什麼要用多執行緒

用多執行緒只有乙個目的,那就是更好的利用cpu的資源,因為所有的多執行緒 都可以用單執行緒來實現。說這個話其實只有一半對,因為反應 多角色 的程式 最起碼每個角色要給他乙個執行緒吧,否則連實際場景都無法模擬,當然也沒法說能用單執行緒來實現 比如最常見的 生產者,消費者模型 就例如乙個網路爬蟲的功能,...

Python 為什麼要用執行緒池?

多執行緒的情況下確實可以最大限度發揮多核處理器的計算能力,提高系統的吞吐量和效能。但是如果隨意使用多執行緒,對系統的效能反而有不利影響。比如下面的情況 建立執行緒是需要時間的,假設執行緒建立所需時間為t1,執行緒執行任務時間為t2,執行緒銷毀時間為t3,而往往t1 t3 t2。所以頻繁建立和銷毀執行...