多線程運行條件下,Thread如何實現線程按順序運行?

原理概述

我們知道,在java多線程運行時,通常線程的運行的先後是“隨機”的——由jvm根據運行時環境調度執行的。

也就是說,這多個線程程序的執行順序是不一定的,它的執行順序還跟線程分的時間片有關。

  CPU運算的時間 是分時間片 分給不同的線程的 一個線程執行完 或者用完了當前它分到的那個時間片 他就得讓出CPU給其他線程使用啦!

  線程化是允許多個活動共存於一個進程中的工具。大多數現代的操作系統都支持線程,而且線程的概念以各種形式已存在了好多年。Java 是第一個在語言本身中顯式地包含線程的主流編程語言,它沒有把線程化看作是底層操作系統的工具。

  有時候,線程也稱作輕量級進程。就象進程一樣,線程在程序中是獨立的、併發的執行路徑,每個線程有它自己的堆棧、自己的程序計數器和自己的局部變量。但是,與分隔的進程相比,進程中的線程之間的隔離程度要小。它們共享內存、文件句柄和其它每個進程應有的狀態。

  進程可以支持多個線程,它們看似同時執行,但互相之間並不同步。一個進程中的多個線程共享相同的內存地址空間,這就意味著它們可以訪問相同的變量和對象,而且它們從同一堆中分配對象。儘管這讓線程之間共享信息變得更容易,但您必須小心,確保它們不會妨礙同一進程裡的其它線程。

  Java 線程工具和 API 看似簡單。但是,編寫有效使用線程的複雜程序並不十分容易。因為有多個線程共存在相同的內存空間中並共享相同的變量,所以您必須小心,確保您的線程不會互相干擾。

  每個 Java 程序都使用線程,  每個 Java 程序都至少有一個線程 ― 主線程。當一個 Java 程序啟動時,JVM 會創建主線程,並在該線程中調用程序的 main() 方法。

那如何實現多個線程的順序執行呢?

其實,可以通過Thread的join方法實現。

順序執行線程

先看個小例子,目標是讓線程按照T3,T2,T1的順序執行。

多線程運行條件下,Thread如何實現線程按順序運行?

多線程運行條件下,Thread如何實現線程按順序運行?

public class T3 implements Runnable {private String threadName;public T3(String name){this.threadName = name;}public void run() {System.out.println("T3 is running:"+threadName);}}

調用執行線程:

public class MySequenceThread {

public static void main(String[] args) {

new Thread(new T1("Thread-T1")).start();

}

}

輸出結果:T1調用T2的join後,T2子線程正常運行,T2調用T3的join後,T3子線程正常運行,T2等待T3運行結束後再運行,T1等待T2運行結束後再運行。運行結果如下圖:

多線程運行條件下,Thread如何實現線程按順序運行?

這裡關鍵的的就是join函數了,join作用:讓主線程等待子線程執行完成後再執行,

源碼分析如下:

public final void join() throws InterruptedException {join(0);}
public final synchronized void join(long millis)throws InterruptedException {long base = System.currentTimeMillis();long now = 0;if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (millis == 0) {while (isAlive()) {wait(0);}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}
public final synchronized void join(long millis, int nanos)throws InterruptedException {if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++;}join(millis);}
public final native boolean isAlive();

最終實際調用的是 public final synchronized void join(long millis) throws InterruptedException 方法,下面看下這個方法:以mils參數為0來解釋

主線程A中調用子線程B的join()方法,同時獲取到了子線程B實例的鎖(其他線程可以進入子線程B的join()方法,但是無法進入子線程B的join(0)方法),join(0)方法一直在調用native方法isAlive()檢測子線程B的狀態,如果子線程B是active的狀態,調用子線程B的wait方法,此時主線程A釋放了鎖(wait方法會釋放鎖),其他線程可以競爭子線程B的實例鎖。如果檢測到子線程B的狀態不是active,主線程A繼續運行。


多線程運行條件下,Thread如何實現線程按順序運行?


分享到:


相關文章: