1. 程式人生 > >多執行緒——join()、sleep()

多執行緒——join()、sleep()

Thread類的方法中有一個join()方法,它是普通的例項方法,根據Java api,該方法有如下三種形式:

void join(): Waits for this thread to die.
void join(long millis): Waits at most millis milliseconds for this thread to die.
void join(long millis, int nanos): Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

該方法的作用是“等待該執行緒終止”,一直等待,直到程終止,而帶引數的方法的作用是“ 等待該執行緒終止,至多等待多少毫秒數 (或毫秒數+納秒數)”。

在此之前,我對這個方法一直有兩個疑問,困惑不解:

  1. 為什麼這個方法的作用是等待該執行緒終止,為什麼它的名字是“加入”的意思?
  2. 在這個等待的關係中,到底是誰等待誰?

在看了很多人的部落格、看了這個方法的原始碼、看了《Java多執行緒程式設計核心技術》這本書和實踐之後,我的理解如下,作為自我學習總結。

1. join()的原始碼分析

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; } } }

join(long millis)方法的原始碼如上所示,首先該方式是synchronized,其次它的實現原理是呼叫了wait()方法。

2. join()/wait()與sleep()的區別

由上,所以join()和sleep()這兩個方法的區別,本質上是wait()和sleep()這兩個方法的區別。

wait()和sleep()的區別:

  • 這兩個方法來自不同的類,wait()方法來自Object類,sleep()方法來自Thread類;
  • wait()方法有三種形式:wait()、wait(long timeout)、wait(long timeout, int nanos),而sleep()方法兩種形式:sleep(long millis)、sleep(long millis, int nanos),即sleep()方法沒有無參形式。其次,sleep()方法是靜態方法。
  • 其實區別主要還是來自於這兩個方法對同步的處理上:wait()方法會釋放鎖,sleep()方法不釋放鎖。在sleep()方法的原始碼中有這樣一句話:

The thread does not lose ownership of any monitors.

所以join()和sleep()這兩個方法的區別,來自於它們對同步的處理上,如上第三條。

3. join()的作用分析

join()方法具有使執行緒依次序列執行的作用,也就是使執行緒排隊執行。對於t.join()語句,其中的等待關係如下:
join()方法的作用是使執行緒t正常執行run()方法中的任務,而使當前執行緒s一直等待執行緒t終止,
在很多情況下,主執行緒生成並起動了子執行緒,所以執行緒s有可能是主執行緒,也有可能是其它子執行緒。
也就是t.join()方法後面的程式碼,只有等到t執行緒結束了才能執行。join()方法的使用方式是線上程t啟動後直接呼叫。

程式碼例項:

功能:三個執行緒,一個列印A,一個列印B,一個列印C,打印出6個連續的ABC。

/*
 * 三個執行緒, 一個列印A, 一個列印B, 一個列印C, 打印出6個連續的ABC.
 */
public class PrintABC implements Runnable {
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("A")){
                System.out.print("A");
        }
        if(Thread.currentThread().getName().equals("B")){
                System.out.print("B");
        }
        if(Thread.currentThread().getName().equals("C")){
                System.out.print("C");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for(int i=0; i<6; i++){
            PrintABC r = new PrintABC();
            Thread A = new Thread(r, "A");
            A.start();
            A.join();
            Thread B = new Thread(r, "B");
            B.start();
            B.join();
            Thread C = new Thread(r, "C");
            C.start();
            C.join();
        }
    }
}

執行結果:

這裡寫圖片描述

嘻嘻~

這裡寫圖片描述