<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Thread.sleep(0) 到底有什么用?

          共 3244字,需瀏覽 7分鐘

           ·

          2022-08-25 18:33

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          作者:走過(guò)路過(guò)ボ不要錯(cuò)過(guò)

          來(lái)源:www.cnblogs.com/keyyang/p/4128424.html


          我們可能經(jīng)常會(huì)用到 Thread.Sleep 函數(shù)來(lái)吧使線程掛起一段時(shí)間。那么你有沒有正確的理解這個(gè)函數(shù)的用法呢?

          思考下面這兩個(gè)問(wèn)題:

          假設(shè)現(xiàn)在是 2008-4-7 12:00:00.000,如果我調(diào)用一下 Thread.Sleep(1000) ,在 2008-4-7 12:00:01.000 的時(shí)候,這個(gè)線程會(huì)不會(huì)被喚醒?

          某人的代碼中用了一句看似莫明其妙的話:Thread.Sleep(0) 。既然是 Sleep 0 毫秒,那么他跟去掉這句代碼相比,有啥區(qū)別么?

          我們先回顧一下操作系統(tǒng)原理

          操作系統(tǒng)中,CPU競(jìng)爭(zhēng)有很多種策略。Unix系統(tǒng)使用的是時(shí)間片算法,而Windows則屬于搶占式的。

          在時(shí)間片算法中,所有的進(jìn)程排成一個(gè)隊(duì)列。操作系統(tǒng)按照他們的順序,給每個(gè)進(jìn)程分配一段時(shí)間,即該進(jìn)程允許運(yùn)行的時(shí)間。如果在時(shí)間片結(jié)束時(shí)進(jìn)程還在運(yùn)行,則CPU將被剝奪并分配給另一個(gè)進(jìn)程。如果進(jìn)程在時(shí)間片結(jié)束前阻塞或結(jié)束,則CPU當(dāng)即進(jìn)行切換。調(diào)度程 序所要做的就是維護(hù)一張就緒進(jìn)程列表,當(dāng)進(jìn)程用完它的時(shí)間片后,它被移到隊(duì)列的末尾。

          所謂搶占式操作系統(tǒng),就是說(shuō)如果一個(gè)進(jìn)程得到了 CPU 時(shí)間,除非它自己放棄使用 CPU ,否則將完全霸占 CPU 。因此可以看出,在搶 占式操作系統(tǒng)中,操作系統(tǒng)假設(shè)所有的進(jìn)程都是“人品很好”的,會(huì)主動(dòng)退出 CPU 。

          在搶占式操作系統(tǒng)中,假設(shè)有若干進(jìn)程,操作系統(tǒng)會(huì)根據(jù)他們的優(yōu)先級(jí)、饑餓時(shí)間(已經(jīng)多長(zhǎng)時(shí)間沒有使用過(guò) CPU 了),給他們算出一 個(gè)總的優(yōu)先級(jí)來(lái)。操作系統(tǒng)就會(huì)把 CPU 交給總優(yōu)先級(jí)最高的這個(gè)進(jìn)程。當(dāng)進(jìn)程執(zhí)行完畢或者自己主動(dòng)掛起后,操作系統(tǒng)就會(huì)重新計(jì)算一 次所有進(jìn)程的總優(yōu)先級(jí),然后再挑一個(gè)優(yōu)先級(jí)最高的把 CPU 控制權(quán)交給他。

          我們用分蛋糕的場(chǎng)景來(lái)描述這兩種算法。假設(shè)有源源不斷的蛋糕(源源不斷的時(shí)間),一副刀叉(一個(gè)CPU),10個(gè)等待吃蛋糕的人(10 個(gè)進(jìn)程)。

          如果是 Unix操作系統(tǒng)來(lái)負(fù)責(zé)分蛋糕,那么他會(huì)這樣定規(guī)矩:每個(gè)人上來(lái)吃 1 分鐘,時(shí)間到了換下一個(gè)。最后一個(gè)人吃完了就再?gòu)念^開始。于是,不管這10個(gè)人是不是優(yōu)先級(jí)不同、饑餓程度不同、飯量不同,每個(gè)人上來(lái)的時(shí)候都可以吃 1 分鐘。當(dāng)然,如果有人本來(lái)不太餓,或者飯量小,吃了30秒鐘之后就吃飽了,那么他可以跟操作系統(tǒng)說(shuō):我已經(jīng)吃飽了(掛起)。于是操作系統(tǒng)就會(huì)讓下一個(gè)人接著來(lái)。

          如果是 Windows 操作系統(tǒng)來(lái)負(fù)責(zé)分蛋糕的,那么場(chǎng)面就很有意思了。他會(huì)這樣定規(guī)矩:我會(huì)根據(jù)你們的優(yōu)先級(jí)、饑餓程度去給你們每個(gè)人計(jì)算一個(gè)優(yōu)先級(jí)。優(yōu)先級(jí)最高的那個(gè)人,可以上來(lái)吃蛋糕——吃到你不想吃為止。等這個(gè)人吃完了,我再重新根據(jù)優(yōu)先級(jí)、饑餓程度來(lái)計(jì)算每個(gè)人的優(yōu)先級(jí),然后再分給優(yōu)先級(jí)最高的那個(gè)人。

          這樣看來(lái),這個(gè)場(chǎng)面就有意思了——可能有些人是PPMM,因此具有高優(yōu)先級(jí),于是她就可以經(jīng)常來(lái)吃蛋糕??赡芰硗庖粋€(gè)人是個(gè)丑男,而去很ws,所以優(yōu)先級(jí)特別低,于是好半天了才輪到他一次(因?yàn)殡S著時(shí)間的推移,他會(huì)越來(lái)越饑餓,因此算出來(lái)的總優(yōu)先級(jí)就會(huì)越來(lái)越高,因此總有一天會(huì)輪到他的)。而且,如果一不小心讓一個(gè)大胖子得到了刀叉,因?yàn)樗埩看?,可能他?huì)霸占著蛋糕連續(xù)吃很久很久,導(dǎo)致旁邊的人在那里咽口水。。。

          而且,還可能會(huì)有這種情況出現(xiàn):操作系統(tǒng)現(xiàn)在計(jì)算出來(lái)的結(jié)果,5號(hào)PPMM總優(yōu)先級(jí)最高,而且高出別人一大截。因此就叫5號(hào)來(lái)吃蛋糕。5號(hào)吃了一小會(huì)兒,覺得沒那么餓了,于是說(shuō)“我不吃了”(掛起)。因此操作系統(tǒng)就會(huì)重新計(jì)算所有人的優(yōu)先級(jí)。因?yàn)?號(hào)剛剛吃過(guò),因此她的饑餓程度變小了,于是總優(yōu)先級(jí)變小了;而其他人因?yàn)槎嗟攘艘粫?huì)兒,饑餓程度都變大了,所以總優(yōu)先級(jí)也變大了。不過(guò)這時(shí)候仍然有可能5號(hào)的優(yōu)先級(jí)比別的都高,只不過(guò)現(xiàn)在只比其他的高一點(diǎn)點(diǎn)——但她仍然是總優(yōu)先級(jí)最高的啊。因此操作系統(tǒng)就會(huì)說(shuō):5號(hào)mm上來(lái)吃蛋糕……(5號(hào)mm心里郁悶,這不剛吃過(guò)嘛……人家要減肥……誰(shuí)叫你長(zhǎng)那么漂亮,獲得了那么高的優(yōu)先級(jí))。

          那么,Thread.Sleep 函數(shù)是干嗎的呢?還用剛才的分蛋糕的場(chǎng)景來(lái)描述。上面的場(chǎng)景里面,5號(hào)MM在吃了一次蛋糕之后,覺得已經(jīng)有8分飽了,她覺得在未來(lái)的半個(gè)小時(shí)之內(nèi)都不想再來(lái)吃蛋糕了,那么她就會(huì)跟操作系統(tǒng)說(shuō):在未來(lái)的半個(gè)小時(shí)之內(nèi)不要再叫我上來(lái)吃蛋糕了。這樣,操作系統(tǒng)在隨后的半個(gè)小時(shí)里面重新計(jì)算所有人總優(yōu)先級(jí)的時(shí)候,就會(huì)忽略5號(hào)mm。Sleep函數(shù)就是干這事的,他告訴操作系統(tǒng)“在未來(lái)的多少毫秒內(nèi)我不參與CPU競(jìng)爭(zhēng)”。

          看完了 Thread.Sleep 的作用,我們?cè)賮?lái)想想文章開頭的兩個(gè)問(wèn)題

          第一個(gè)問(wèn)題?

          對(duì)于第一個(gè)問(wèn)題,答案是:不一定。因?yàn)槟阒皇歉嬖V操作系統(tǒng):在未來(lái)的1000毫秒內(nèi)我不想再參與到CPU競(jìng)爭(zhēng)。那么1000毫秒過(guò)去之后,這時(shí)候也許另外一個(gè)線程正在使用CPU,那么這時(shí)候操作系統(tǒng)是不會(huì)重新分配CPU的,直到那個(gè)線程掛起或結(jié)束;況且,即使這個(gè)時(shí)候恰巧輪到操作系統(tǒng)進(jìn)行CPU 分配,那么當(dāng)前線程也不一定就是總優(yōu)先級(jí)最高的那個(gè),CPU還是可能被其他線程搶占去。

          與此相似的,Thread有個(gè)Resume函數(shù),是用來(lái)喚醒掛起的線程的。好像上面所說(shuō)的一樣,這個(gè)函數(shù)只是“告訴操作系統(tǒng)我從現(xiàn)在起開始參與CPU競(jìng)爭(zhēng)了”,這個(gè)函數(shù)的調(diào)用并不能馬上使得這個(gè)線程獲得CPU控制權(quán)。

          第二個(gè)問(wèn)題?

          對(duì)于第二個(gè)問(wèn)題,答案是:有,而且區(qū)別很明顯。假設(shè)我們剛才的分蛋糕場(chǎng)景里面,有另外一個(gè)PPMM 7號(hào),她的優(yōu)先級(jí)也非常非常高(因?yàn)榉浅7浅F粒?,所以操作系統(tǒng)總是會(huì)叫道她來(lái)吃蛋糕。而且,7號(hào)也非常喜歡吃蛋糕,而且飯量也很大。不過(guò),7號(hào)人品很好,她很善良,她沒吃幾口就會(huì)想:如果現(xiàn)在有別人比我更需要吃蛋糕,那么我就讓給他。因此,她可以每吃幾口就跟操作系統(tǒng)說(shuō):我們來(lái)重新計(jì)算一下所有人的總優(yōu)先級(jí)吧。不過(guò),操作系統(tǒng)不接受這個(gè)建議——因?yàn)椴僮飨到y(tǒng)不提供這個(gè)接口。于是7號(hào)mm就換了個(gè)說(shuō)法:“在未來(lái)的0毫秒之內(nèi)不要再叫我上來(lái)吃蛋糕了”。這個(gè)指令操作系統(tǒng)是接受的,于是此時(shí)操作系統(tǒng)就會(huì)重新計(jì)算大家的總優(yōu)先級(jí)——注意這個(gè)時(shí)候是連7號(hào)一起計(jì)算的,因?yàn)椤?毫秒已經(jīng)過(guò)去了”嘛。因此如果沒有比7號(hào)更需要吃蛋糕的人出現(xiàn),那么下一次7號(hào)還是會(huì)被叫上來(lái)吃蛋糕。

          因此,Thread.Sleep(0)的作用,就是“觸發(fā)操作系統(tǒng)立刻重新進(jìn)行一次CPU競(jìng)爭(zhēng)”。競(jìng)爭(zhēng)的結(jié)果也許是當(dāng)前線程仍然獲得CPU控制權(quán),也許會(huì)換成別的線程獲得CPU控制權(quán)。這也是我們?cè)诖笱h(huán)里面經(jīng)常會(huì)寫一句Thread.Sleep(0) ,因?yàn)檫@樣就給了其他線程比如Paint線程獲得CPU控制權(quán)的權(quán)力,這樣界面就不會(huì)假死在那里。

          另外,雖然上面提到說(shuō)“除非它自己放棄使用 CPU ,否則將完全霸占 CPU”,但這個(gè)行為仍然是受到制約的——操作系統(tǒng)會(huì)監(jiān)控你霸占CPU的情況,如果發(fā)現(xiàn)某個(gè)線程長(zhǎng)時(shí)間霸占CPU,會(huì)強(qiáng)制使這個(gè)線程掛起,因此在實(shí)際上不會(huì)出現(xiàn)“一個(gè)線程一直霸占著 CPU 不放”的情況。至于我們的大循環(huán)造成程序假死,并不是因?yàn)檫@個(gè)線程一直在霸占著CPU。
          實(shí)際上在這段時(shí)間操作系統(tǒng)已經(jīng)進(jìn)行過(guò)多次CPU競(jìng)爭(zhēng)了,只不過(guò)其他線程在獲得CPU控制權(quán)之后很短時(shí)間內(nèi)馬上就退出了,于是就又輪到了這個(gè)線程繼續(xù)執(zhí)行循環(huán),于是就又用了很久才被操作系統(tǒng)強(qiáng)制掛起。。。因此反應(yīng)到界面上,看起來(lái)就好像這個(gè)線程一直在霸占著CPU一樣。

              

          1、社區(qū)糾紛不斷:程序員何苦為難程序員?

          2、該死的單元測(cè)試,寫起來(lái)到底有多痛?

          3、互聯(lián)網(wǎng)人為什么學(xué)不會(huì)擺爛

          4、為什么國(guó)外JetBrains做 IDE 就可以養(yǎng)活自己,國(guó)內(nèi)不行?區(qū)別在哪?

          5、相比高人氣的Rust、Go,為何 Java、C 在工具層面進(jìn)展緩慢?

          6、讓程序員早點(diǎn)下班的《技術(shù)寫作指南》

          點(diǎn)

          點(diǎn)

          點(diǎn)點(diǎn)

          點(diǎn)在看

          瀏覽 19
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲国产天堂 | 内射久久视频 | 水蜜桃视频网 | 国产三级大全 | 欧美日韩中文字幕在线视频 |