Thread.join()笔记

首先看下javadoc的介绍

https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join--

https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join-long-

https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join-long-int-

Thread.join()笔记_第1张图片

Thread.join()笔记_第2张图片

Thread.join()笔记_第3张图片

从javadoc的介绍可以看出,Thread.join()方法就是要等待线程结束。

具体实现方法:循环的检查Thread.isAlive(),如果返回true,则进入Thread.wait();等待线程执行完毕后,Thread.notifyAll()会被触发,然后检查Thread.isAlive(),此时会返回false,Thread.join()方法返回。

看一下Thread.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;
		}
	}
}

核心代码:

while (isAlive()) {
	wait(0);
}

且join()方法具有synchronized标识,进入join()方法需要获取Thread对象的锁。

如果进入join()方法时,线程已经执行结束,那么isAive()方法返回false,join()方法直接返回;

如果进入join()方法时,线程还在执行,那么isAlive()方法返回true,进入wait(),线程执行结束退出时,JVM会调用Thread.notifyAll()方法,唤醒wait()中的线程,join()方法返回。

从openjdk源码中可以看到调用Thread.notifyAll()的地方:openjdk\hotspot\src\share\vm\runtime\thread.cpp中的JavaThread::exit(bool destroy_vm, ExitType exit_type)方法中的ensure_join()

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
  assert(this == JavaThread::current(),  "thread consistency check");

  HandleMark hm(this);
  Handle uncaught_exception(this, this->pending_exception());
  this->clear_pending_exception();
  Handle threadObj(this, this->threadObj());
  assert(threadObj.not_null(), "Java thread object should be created");

  if (get_thread_profiler() != NULL) {
    get_thread_profiler()->disengage();
    ResourceMark rm;
    get_thread_profiler()->print(get_thread_name());
  }

......
  
  // Notify waiters on thread object. This has to be done after exit() is called
  // on the thread (if the thread is the last thread in a daemon ThreadGroup the
  // group should have the destroyed bit set before waiters are notified).
  ensure_join(this);
  assert(!this->has_pending_exception(), "ensure_join should have cleared");

  // 6282335 JNI DetachCurrentThread spec states that all Java monitors
  // held by this thread must be released.  A detach operation must only
  // get here if there are no Java frames on the stack.  Therefore, any
  // owned monitors at this point MUST be JNI-acquired monitors which are
  // pre-inflated and in the monitor cache.
  //
  // ensure_join() ignores IllegalThreadStateExceptions, and so does this.
  if (exit_type == jni_detach && JNIDetachReleasesMonitors) {
    assert(!this->has_last_Java_frame(), "detaching with Java frames?");
    ObjectSynchronizer::release_monitors_owned_by_thread(this);
    assert(!this->has_pending_exception(), "release_monitors should have cleared");
  }

......

  // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
  Threads::remove(this);
}

Thread.join()笔记_第4张图片


你可能感兴趣的:(Java)