深入理解並發編程 -- 多線程(二)底層運行原理、線程狀態


並發編程 -- 多線程底層運行原理、線程狀態

作者 : Stanley 羅昊

多線程 -- 並發編程(一) : https://www.cnblogs.com/StanleyBlogs/p/10890906.html

轉載請注明出處和署名,謝謝!

多線程底層執行原理

說道底層運行,那么是不是就是需要依靠CPU啊;

那,各位之前有沒有聽過一句話叫做,一個CPU在同一個時間片只能執行一個程序

什么意思呢?

就是,你的程序是不是都運行在一個CPU上啊,那你真正一個CPU在同一個時間片里是不是只能執行一個程序呀,那這個程序究竟要執行那個程序,是不是就需要通過線程之間時間片的一個爭搶;

時間片:微小的時間段;

多線程說白了就是時間片的爭奪,那個線程獲取了時間片,就執行那個線程的代碼;

假設,t1線程先獲得時間片,那么,t1線程就優先執行;

但是,它不可能拿着那個時間片不放吧,因為在CPU執行的過程中,底層運用輪循制的;

多線程執行的時候,CPU分配時間片是采取輪循的方式進行分配的;

就是輪流,有點像值日的時候,輪流值日一樣;

那,CPU在分配時間片的時候,第一個t1先搶占到了之后,他先執行了一段時間之后,CPU把這個t1執行完了以后,CPU是不是接着把時間片分配給t2去執行了;

那事實上,也是t2也在去搶占時間片

t1執行完畢后,那么,CPU就將迎來新的一輪爭奪,這個時候t2搶到了,就開始執行t2的代碼;

這就是多線程的底層執行原理;

多線程它在本質上運行的時候,他是同時執行的,還是輪流執行的呢?

肯定不是同時執行的,也就是不是我們常說的並發執行;那在你們看來,實際就是宏觀上你來看就是同時執行,但是在微觀上是不是的;

線程的狀態

線程總共有五種狀態;

第一個狀態 新建狀態

新建狀態,就是你新建一個線程是的狀態,也就是你新建了一個線程但還沒有啟動時的狀態;

當線程執行start方法的時候,就會進入就緒狀態;

第二個狀態 就緒狀態

進入就緒狀態的時候,事實上就是准備搶占CPU的時間片;

一旦搶占到了CPU的時間片它就會立即進入運行狀態;

第三個狀態 運行狀態

當線程搶占到了CPU時間片的時候,它才會運行,所以第三個狀態是,運行狀態;

在它的運行狀態中,還有可能執行一個代碼,Throad.sleep();睡眠;

就是在你執行的時候,突然讓你睡眠了,我都讓你這個線程睡眠了,你還有必要去爭奪這個CPU資源嗎?

就肯定沒有必要再去爭奪這個CPU資源了,那這個時候你就需要釋放CPU啊,對不對,你釋放之后,你下次再運行的時候,你就需要重新獲取CPU的時間片,所以這種狀態就叫做堵塞狀態;

第四個狀態 堵塞狀態與sleep方法

想讓線程阻塞,最常用的方式就是使用sleep,用sleep這個方法,可以使運行中的線程回到就緒狀態;

因為它需要重新搶占CPU資源的,所以,sleep狀態的最終目的是讓改線程回到就讀狀態;

就比如,我現在想讓這個線程,進我想讓它每次進入run方法中的for循環打印里寫一個睡眠,一遍循環遍歷輸出,一邊睡眠看會發生什么:

我在run方法中業務寫完后,我們測試一下該線程:

在上圖中,可以發現,我同時調用了兩次start方法,說明,我執行了兩次我一次性開啟了兩次線程,並且執行了兩次,我們看看會不會出現交替執行的情況:

從輸出結果來看,確實交替執行了並且,是倆倆執行的:

每過一秒,就會執行一次:

我就不繼續演示了;

所以,我們從中可以看出,不管哪個線程過來,t1也好t2也好,執行的時候,均睡眠一秒鍾,睡眠完一秒鍾之后,誰先醒了,誰就繼續向下執行,這個就是到點自然醒的;

也可以使用join來造成線程堵塞;

join

剛剛,我們在上面介紹了sleep,我們來看看join;

join():是線程加入

它底層執行的是,當你在執行一個線程的時候,如果遇到其他線程加入,則會先執行加入的線程,直到的加入的線程執行完成,才會繼續執行原來線程的任務;

什么意思呢?

就是說,還是上面那個t1,與t2的例子,那假設說,t1在執行的過程中,突然遇到了一個代碼t2.join,這時候,就會在這個時間片,優先執行t2的線程;

join()方法可以給一個參數,參數代表執行的毫秒; 

第五個狀態 死亡狀態

線程執行完了,或因異常退出了,都會結束生命周期,這就是死亡狀態;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM