1. 程式人生 > >Thread執行緒join方法原始碼分析

Thread執行緒join方法原始碼分析

最近在複習執行緒的基礎知識,算是查漏補缺,溫故知新吧。

join原始碼

public final synchronized void join(long var1) throws InterruptedException {
        //獲取當前系統時間
        long var3 = System.currentTimeMillis();
        //記錄已經過的時間
        long var5 = 0L;
        //wait時間不能小於0l
        if(var1 < 0L) {
            throw new IllegalArgumentException("timeout value is negative"
); } else { //如果休眠時間位為0,則表示呼叫執行緒一直要等到這個執行緒結束才停止等待 if(var1 == 0L) { while(this.isAlive()) { //等待 wait(0L); } } else { while(this.isAlive()) { //算出剩餘等待時間,到達後結束wait
long var7 = var1 - var5; if(var7 <= 0L) { break; } wait(var7); //計算已經等待的時長 var5 = System.currentTimeMillis() - var3; } } } }

使用示例

public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main start");

        Thread t1 = new Thread(new Worker("thread-1"));
        t1.start();
        //main執行緒等待t1結束,然後輸出main end
        t1.join();
        System.out.println("main end");
    }

注意

Causes the current thread to wait until either another thread invokes the java.lang.Object.notify() method or the java.lang.Object.notifyAll() method for this object, or a specified amount of time has elapsed.

wait()方法是Object的方法,標識執行當前物件wait方法的執行緒陷入等待狀態,示例中:thread t1是物件,main執行緒呼叫t1的join方法的執行緒。首先是得到t1物件的鎖,之後呼叫t1的wait()方法後,主執行緒將進入等待狀態並釋放其持有的該物件上的鎖(執行緒仍然持有其它物件的鎖)。

Javadoc對wait()方法的詳細描述如下,感興趣的可以看看:

Causes the current thread to wait until either another thread invokes the java.lang.Object.notify() method or the java.lang.Object.notifyAll() method for this object, or a specified amount of time has elapsed.

The current thread must own this object's monitor.

This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

Some other thread invokes the notify method for this object and thread T happens to bearbitrarily chosen as the thread to be awakened. (參見notify()方法的JavadocIf any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation)
Some other thread invokes the notifyAll method for this object.
Some other thread interrupts thread T.
The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.

A thread can also wake up without being notified, interrupted, or timing out, a so-calledspurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:

synchronized (obj) {
    while (<condition does not hold>)
            obj.wait(timeout);
            ... // Perform action appropriate to condition
}
If the current thread is interrupted by any thread before or while it is waiting, then anInterruptedException is thrown. This exception is not thrown until the lock status of this object has been restored as described above.

Note that the wait method, as it places the current thread into the wait set for this object, unlocks only this object; any other objects on which the current thread may be synchronized remain locked while the thread waits. (這點要特別注意)

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways(簡單來說就是獲取該物件的鎖):

By executing a synchronized instance method of that object(呼叫該物件的同步方法).
By executing the body of a synchronized statement that synchronizes on the object(進入該物件的同步程式碼塊).
For objects of type Class, by executing a synchronized static method of that class(呼叫該物件的同步靜態方法).
Only one thread at a time can own an object's monitor.