做者 : Stanley 羅昊html
多線程 -- 併發編程(一) : https://www.cnblogs.com/StanleyBlogs/p/10890906.html編程
【轉載請註明出處和署名,謝謝!】多線程
說道底層運行,那麼是否是就是須要依靠CPU啊;併發
那,各位以前有沒有聽過一句話叫作,一個CPU在同一個時間片只能執行一個程序;測試
什麼意思呢?spa
就是,你的程序是否是都運行在一個CPU上啊,那你真正一個CPU在同一個時間片裏是否是隻能執行一個程序呀,那這個程序究竟要執行那個程序,是否是就須要經過線程之間時間片的一個爭搶;線程
時間片:微小的時間段;3d
多線程說白了就是時間片的爭奪,那個線程獲取了時間片,就執行那個線程的代碼;htm
假設,t1線程先得到時間片,那麼,t1線程就優先執行;blog
可是,它不可能拿着那個時間片不放吧,由於在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這個方法,可使運行中的線程回到就緒狀態;
由於它須要從新搶佔CPU資源的,因此,sleep狀態的最終目的是讓改線程回到就讀狀態;
就好比,我如今想讓這個線程,進我想讓它每次進入run方法中的for循環打印裏寫一個睡眠,一遍循環遍歷輸出,一邊睡眠看會發生什麼:
我在run方法中業務寫完後,咱們測試一下該線程:
在上圖中,能夠發現,我同時調用了兩次start方法,說明,我執行了兩次我一次性開啓了兩次線程,而且執行了兩次,咱們看看會不會出現交替執行的狀況:
從輸出結果來看,確實交替執行了而且,是倆倆執行的:
每過一秒,就會執行一次:
我就不繼續演示了;
因此,咱們從中能夠看出,無論哪一個線程過來,t1也好t2也好,執行的時候,均睡眠一秒鐘,睡眠完一秒鐘以後,誰先醒了,誰就繼續向下執行,這個就是到點天然醒的;
也可使用join來形成線程堵塞;
剛剛,咱們在上面介紹了sleep,咱們來看看join;
join():是線程加入
它底層執行的是,當你在執行一個線程的時候,若是遇到其餘線程加入,則會先執行加入的線程,直到的加入的線程執行完成,纔會繼續執行原來線程的任務;
什麼意思呢?
就是說,仍是上面那個t1,與t2的例子,那假設說,t1在執行的過程當中,忽然遇到了一個代碼t2.join,這時候,就會在這個時間片,優先執行t2的線程;
join()方法能夠給一個參數,參數表明執行的毫秒;
線程執行完了,或因異常退出了,都會結束生命週期,這就是死亡狀態;