面试官:Thread.sleep(0) 有什么用?
點(diǎn)擊上方“朱小廝的博客”,選擇“設(shè)為星標(biāo)”
后臺(tái)回復(fù)"加群",加入新技術(shù)
我們可能經(jīng)常會(huì)用到 Thread.Sleep 函數(shù)來吧使線程掛起一段時(shí)間。那么你有沒有正確的理解這個(gè)函數(shù)的用法呢?
思考下面這兩個(gè)問題:
假設(shè)現(xiàn)在是 2020-05-24 12:00:00.000,如果我調(diào)用一下 Thread.Sleep(1000) ,在 2020-05-24 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),就是說如果一個(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í)間沒有使用過 CPU 了),給他們算出一個(gè)總的優(yōu)先級(jí)來。操作系統(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)交給他。
Sleep函數(shù)就是告訴操作系統(tǒng)“在未來的多少毫秒內(nèi)我不參與CPU競(jìng)爭(zhēng)”。
對(duì)于第一個(gè)問題,答案是:不一定。因?yàn)槟阒皇歉嬖V操作系統(tǒng):在未來的1000毫秒內(nèi)我不想再參與到CPU競(jìng)爭(zhēng)。那么1000毫秒過去之后,這時(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ù),是用來喚醒掛起的線程的。好像上面所說的一樣,這個(gè)函數(shù)只是“告訴操作系統(tǒng)我從現(xiàn)在起開始參與CPU競(jìng)爭(zhēng)了”,這個(gè)函數(shù)的調(diào)用并不能馬上使得這個(gè)線程獲得CPU控制權(quán)。
對(duì)于第二個(gè)問題,答案是:有,而且區(qū)別很明顯。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ì)假死在那里。
另外,雖然上面提到說“除非它自己放棄使用 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)行過多次CPU競(jìng)爭(zhēng)了,只不過其他線程在獲得CPU控制權(quán)之后很短時(shí)間內(nèi)馬上就退出了,于是就又輪到了這個(gè)線程繼續(xù)執(zhí)行循環(huán),于是就又用了很久才被操作系統(tǒng)強(qiáng)制掛起。。。因此反應(yīng)到界面上,看起來就好像這個(gè)線程一直在霸占著CPU一樣。
想知道更多?掃描下面的二維碼關(guān)注我
后臺(tái)回復(fù)”加群“獲取公眾號(hào)專屬群聊入口
當(dāng)當(dāng)618圖書優(yōu)惠活動(dòng),每滿100-50,我這里還有一批“實(shí)付滿200再減30”的優(yōu)惠碼TEGNC6?,囤書薅羊毛再走一波~~(使用時(shí)間:5月18~6月1日,使用渠道:當(dāng)當(dāng)小程序或當(dāng)當(dāng)APP)
【原創(chuàng)系列 | 精彩推薦】
Paxos、Raft不是一致性算法嘛?
越說越迷糊的CAP
分布式事務(wù)科普——初識(shí)篇
分布式事務(wù)科普——終結(jié)篇
面試官居然問我Raft為什么會(huì)叫做Raft!
面試官給我挖坑:URI中的//有什么用
面試官給我挖坑:a[i][j]和a[j][i]有什么區(qū)別?
面試官給我挖坑:單機(jī)并發(fā)TCP連接數(shù)到底有多少?
網(wǎng)關(guān)Zuul科普
網(wǎng)關(guān)Spring Cloud?Gateway科普
Nginx架構(gòu)原理科普
OpenResty概要及原理科普
微服務(wù)網(wǎng)關(guān) Kong 科普
云原生網(wǎng)關(guān)Traefik科普
點(diǎn)個(gè)在看少個(gè) bug?????
總結(jié)
以上是生活随笔為你收集整理的面试官:Thread.sleep(0) 有什么用?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTTP/3 未来可期?
- 下一篇: 再见,Navicat!这个IDEA的兄弟