前言
初學(xué)者學(xué)習(xí)編程時(shí),很容易因?yàn)槎嗑€程出現(xiàn)各種問題,導(dǎo)致不敢使用多線程。但是多線程技術(shù)在做開發(fā)中,是不可忽視的一個(gè)技術(shù),基本上我們實(shí)際應(yīng)用中,每個(gè)項(xiàng)目都會(huì)使用多線程,所以多線程技術(shù)必須掌握。
為什么要用多線程
隨著工業(yè)的進(jìn)步,現(xiàn)在的筆記本、臺(tái)式機(jī)大都是雙核的,4核、8核甚至16核,也很常見,如果是單線程的程序,那么在雙核CPU上就浪費(fèi)了50%,在4核CPU上就浪費(fèi)了75%。
單核CPU上所謂的”多線程”那是假的多線程,同一時(shí)間處理器只會(huì)處理一段邏輯,只不過線程之間切換得比較快,看著像多個(gè)線程”同時(shí)”運(yùn)行罷了。
多核CPU上的多線程才是真正的多線程,它能讓你的多段邏輯同時(shí)工作,多線程,可以真正發(fā)揮出多核CPU的優(yōu)勢(shì)來,達(dá)到充分利用CPU的目的。
如果你做項(xiàng)目不使用多線程,不僅是技術(shù)的問題,也是對(duì)電腦資源的極大浪費(fèi),就像你買了一輛配置非常高的越野車,你僅僅只用它來日常代步一樣。3
為什么不敢用多線程
之前跟一些學(xué)員溝通時(shí)發(fā)現(xiàn),很多學(xué)員之所以不敢使用多線程,是因?yàn)橹俺鲞^問題,有種“一朝被蛇咬,十年怕井繩”的感覺。
為什么多線程容易出問題,有個(gè)主要的原因在于多線程充滿著“未知性”,有的人使用時(shí),發(fā)現(xiàn)代碼并沒有按照預(yù)想的流程在走,這其實(shí)是正常的。
我們必須要明確一點(diǎn),多線程確實(shí)是“不可控的”,有某種意義上來說,多線程是靠CPU調(diào)度來執(zhí)行的,并非人為去控制。
我們所謂的控制多線程,僅僅是.NET框架開放了一些接口給開發(fā)者,這樣可以相對(duì)性地間接控制多線程的啟動(dòng)停止暫停繼續(xù)。
線程的啟動(dòng)停止
線程的啟動(dòng)停止,從.Net Framework 4.5開始,Task提供了一個(gè)叫CancellationTokenSource的對(duì)象,可以使用它來對(duì)多線程的啟停進(jìn)行控制。
首先,我們做一個(gè)線程任務(wù),這個(gè)任務(wù)很簡(jiǎn)單,只是不斷操作某個(gè)變量,每0.1秒加1,到一定值之后,重置為0,然后將這個(gè)值顯示在界面上,界面如下所示:
所以任務(wù)方法如下:
個(gè)對(duì)象就是CancellationTokenSource的對(duì)象,因此我們需要?jiǎng)?chuàng)建一個(gè)CancellationTokenSource對(duì)象cts:
然后在啟動(dòng)線程按鈕的事件里,編寫代碼如下:
停止線程按鈕的事件里,只需要調(diào)用cts的Cancel方法即可:
其實(shí),說白了,就是通過cts來控制cts的IsCancellationRequested屬性,進(jìn)而實(shí)現(xiàn)多線程的控制。
線程的暫停繼續(xù)
多線程的暫停繼續(xù),.NET為我們提供了另外一個(gè)對(duì)象——ManualResetEvent,這個(gè)對(duì)象會(huì)有一個(gè)值,這個(gè)值是布爾類型,就像一個(gè)門閘一樣,True是打開門閘,F(xiàn)alse是關(guān)閉門閘,所以想要暫停多線程就調(diào)用這個(gè)對(duì)象的Reset方法,想要繼續(xù)多線程就調(diào)用這個(gè)對(duì)象的Set方法,使用非常簡(jiǎn)單。
首先我們創(chuàng)建一下這個(gè)對(duì)象,可以通過構(gòu)造方法,給這個(gè)對(duì)象賦初始值,我這里為True,這樣就能直接運(yùn)行,不會(huì)阻塞。
但是如果希望這個(gè)對(duì)象與多線程有所聯(lián)系,必須要在多線程的方法里體現(xiàn)這個(gè)對(duì)象的作用,這個(gè)是調(diào)用這個(gè)對(duì)象的WaitOne方法,表示在調(diào)用的地方阻塞住,通過判斷True或者False來決定是否繼續(xù)執(zhí)行,就像大家開車過高速收費(fèi)站一樣,即使現(xiàn)在普遍采用ETC了,在入口也需要減速,有一個(gè)ETC識(shí)別的過程,識(shí)別成功才會(huì)抬桿,識(shí)別識(shí)別,桿子是不會(huì)自動(dòng)抬起的,這個(gè)是一樣的道理。
所以線程執(zhí)行代碼如下:
對(duì)比一下,其實(shí)就是加了一個(gè)manual.WaitOne()。
線程暫停代碼:
線程繼續(xù)代碼:
AutoResetEvent
AutoResetEvent和ManualResetEvent的用法非常相似,區(qū)別在于一個(gè)是手動(dòng),一個(gè)是自動(dòng),AutoResetEvent會(huì)在置位之后自動(dòng)復(fù)位,這樣體現(xiàn)在多線程里,就是會(huì)只執(zhí)行一次,就像大家進(jìn)小區(qū)一樣,如果有10輛車在排隊(duì),這時(shí)候如果自動(dòng)模式,每次只能進(jìn)一輛車,如果是手動(dòng)模式,可以由保安控制門閘打開,等10輛車都進(jìn)去之后,再由保安將門閘關(guān)注。
-
cpu
+關(guān)注
關(guān)注
68文章
10863瀏覽量
211781 -
多線程
+關(guān)注
關(guān)注
0文章
278瀏覽量
19961 -
變量
+關(guān)注
關(guān)注
0文章
613瀏覽量
28371
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論