咱們在平常的多線程開發中,可能有時會想讓每一個線程都按照咱們指定的順序來運行,而不是讓CPU隨機調度,這樣可能會讓咱們在平常的開發工做中帶來沒必要要的麻煩。既然有了這個需求,也就引入了本文的標題,讓線程按照本身指定的順序來運行。java
有興趣的同窗能夠猜測下列代碼可能運行的結果:安全
按照正常的理解思路,上面代碼的執行順序依次應該爲:t1 → t2 → t3,而實際效果則不是理想的狀態。多線程
下圖爲運行效果:學習
(1)認識Join
join可能對於一些同窗來講並不陌生,此處我就不詳細介紹Join是什麼了,有疑問的同窗能夠自行baidu和google。這裏我將直接介紹如何使用join來達到咱們但願看到的效果!google
這裏主要是利用Join的阻塞效果,來達到咱們的使用目的。看上圖的運行結果能夠得知,程序已經按照咱們指定的順序執行結束了,並獲得了咱們想要的結果。spa
其實這裏能夠深刻的思考一下,爲何join能夠達到咱們想要的效果呢?接下來咱們來看下源碼:線程
進入join源碼後,首先看到的是一個傳入0參數的join方法,此處選擇繼續進入。3d
首先能夠看到join方法是線程安全的,其次能夠結合上圖一塊兒看,當傳入參數爲0時,會命中一個wait(0)的方法,有經驗的同窗應該能直接看懂,這裏表示等待。可是須要說明的是,這裏的等待絕對不是等待調用者,而是阻塞的主線程,t1,t2,t3只是子線程,當子線程運行完畢後,主線程結束等待。這裏演示了join的工做方式,也證明了join能讓咱們在程序中達到本身想要的效果。(即在main主線程中執行t1,t2,t3,若是使用t1.join(),那麼表示在主線程中插入了t1線程,此時main主線程阻塞,須要等待t1線程徹底執行完以後,纔會繼續主線程,即繼續main主線程在t1.join()之下的代碼)code
除了join能在程序中幫助咱們控制線程的順序外,還有另外的方式,好比咱們利用線程池實現試一試。blog
(2)利用Executors線程池
Executors是JDK中java.util.concurrent包下線程池操做類,能夠方便的爲咱們提供線程池的操做。這裏咱們使用Executors中的newSingleThreadExecutor()方法,建立一個單線程的線程池。
(3) 利用Thread.sleep()也能夠達到一樣的效果
try { t1.start(); Thread.sleep(10); t2.start(); Thread.sleep(10); t3.start(); } catch (InterruptedException e1) { e1.printStackTrace(); }
根據上圖能夠得知,利用newSingleThreadExecutor()方法依然可以達到咱們期待的效果,其實原理很簡單,方法內部是一個基於FIFO的隊列,也就是說,當咱們依次將t1,t2,t3加入隊列中時,實際在就緒狀態的只有t1這個線程,t2,t3則會被添加到隊列中,當t1執行完畢後,則會繼續執行隊列中的其餘線程。
本章總結:
根據上面的篇幅咱們得知了如何讓線程按照指定的方式運行,其實方法還有不少,限於篇幅就不一一列舉了,本文只是但願提供給一些基礎很差的同窗以一些思路。本文還有不少細節沒有講解的很清楚,你們能夠根據提供的連接深刻的學習。同時但願你們給予寶貴的意見!