Thread线程join方法源码分析

时间:2021-07-12 00:00:15

最近在复习线程的基础知识,算是查漏补缺,温故知新吧。

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.