1. 程式人生 > >Java中讓執行緒按照自己指定的順序執行

Java中讓執行緒按照自己指定的順序執行

我們在日常的多執行緒開發中,可能有時會想讓每個執行緒都按照我們指定的順序來執行,而不是讓CPU隨機排程,這樣可能會讓我們在日常的開發工作中帶來不必要的麻煩。既然有了這個需求,也就引入了本文的標題,讓執行緒按照自己指定的順序來執行。

有興趣的同學可以猜想下列程式碼可能執行的結果:

按照正常的理解思路,上面程式碼的執行順序依次應該為:t1 → t2 → t3,而實際效果則不是理想的狀態。

下圖為執行效果:

(1)認識Join
join可能對於一些同學來說並不陌生,此處我就不詳細介紹Join是什麼了,有疑問的同學可以自行baidu和google。這裡我將直接介紹如何使用join來達到我們希望看到的效果!

這裡主要是利用Join的阻塞效果,來達到我們的使用目的。看上圖的執行結果可以得知,程式已經按照我們指定的順序執行結束了,並得到了我們想要的結果。

其實這裡可以深入的思考一下,為什麼join可以達到我們想要的效果呢?接下來我們來看下原始碼:

進入join原始碼後,首先看到的是一個傳入0引數的join方法,此處選擇繼續進入。

首先可以看到join方法是執行緒安全的,其次可以結合上圖一起看,當傳入引數為0時,會命中一個wait(0)的方法,有經驗的同學應該能直接看懂,這裡表示等待。但是需要說明的是,這裡的等待絕對不是等待呼叫者,而是阻塞的主執行緒,t1,t2,t3只是子執行緒,當子執行緒執行完畢後,主執行緒結束等待

。這裡演示了join的工作方式,也證實了join能讓我們在程式中達到自己想要的效果。(即在main主執行緒中執行t1,t2,t3,如果使用t1.join(),那麼表示在主執行緒中插入了t1執行緒,此時main主執行緒阻塞,需要等待t1執行緒完全執行完之後,才會繼續主執行緒,即繼續main主執行緒在t1.join()之下的程式碼)

除了join能在程式中幫助我們控制執行緒的順序外,還有另外的方式,比如我們利用執行緒池實現試一試。

(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執行完畢後,則會繼續執行佇列中的其他執行緒。

 

本章總結:

根據上面的篇幅我們得知了如何讓執行緒按照指定的方式執行,其實方法還有很多,限於篇幅就不一一列舉了,本文只是希望提供給一些基礎不好的同學以一些思路。本文還有很多細節沒有講解的很清楚,大家可以根據提供的連結深入的學習。同時希望大家給予寶貴