从一个例子开头:
@Slf4j
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread thread_new = new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}
log.info("Thread------>:{}", Thread.currentThread().getName());
},"thread_new");
thread_new.start();
thread_new.join();
log.info("Thread------>:{}", Thread.currentThread().getName());
log.info("end");
}
}
毫无疑问,会打印:
Thread------>:Thread-0
Thread------>:main
end
在Thread类中:
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;
}
}
}
在主线程中调用 thread_new.join()方法会使主线程阻塞,进入wait()状态,直到thread_new线程执行完毕,那么为什么会产生这样的现象呢。
先从synchronized 说起,synchronized在java中如果作为非静态方法的描述符,则等同于在方法第一行加上
synchronized(this){},这时调用 thread_new.join(),则this指向的是当前的thread_new对象,所以当前thread_new对象的对象头,会指向monitor对象,monitor中指向的线程为主线程,while (isAlive()) {wait(0);},isAlive()为Thread中的方法,会先判断thread_new线程是否存活。显然,isAlive()为true,这时直接调用wait(0)会使当前thread_new对象头中指向的monit对象中,记录的线程(主线程),进入waitSet。使主线程进入wait状态。等到thread_new的线程终结,在jvm中会触发thread_new对象的thread_exit()方法,在该方法中会调用notiyAll()方法,唤醒该对象头中waitSet中的线程。
ObjectMonitor() {
_header = NULL;
_count = 0; //记录个数
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL; //_owner指向持有ObjectMonitor对象的线程
_WaitSet = NULL; //处于wait状态的线程,会被加入到_WaitSet
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ; //处于等待锁block状态的线程,会被加入到该列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}