Java线程源码解析之join

概述

面试时,经常会有面试官会问到Thread.join方法是干吗的?JavaDoc上的结束很简单:

Waits for this thread to die.

意思是说等待线程死亡,今天就一起来看看具体的源码实现;

Thread.join

Thread.join方法可以带参数,也可以不带参数,实际上不带参数时相当于调用Thread.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");
        }
       //参数为0,调用Object.wait(0)等待
        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);//参数非0,调用Object.wait(time)等待
                now = System.currentTimeMillis() - base;
            }
        }
    }

从上面的源码可以看到,逻辑实现比较简单,通过while循环查看线程状态(isAlive()),如果线程活着,调用Object.wait()方法等待;

那么:

  1. 如何判断线程是否活着呢?
  2. wait()方法是在什么时候被唤醒的呢?

isAlive是个native方法,具体实现在jvm.cpp文件:

JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_IsThreadAlive");

  oop thread_oop = JNIHandles::resolve_non_null(jthread);
  return java_lang_Thread::is_alive(thread_oop);
JVM_END

java_lang_Thread::is_alive在javaClasses.cpp文件定义:

bool java_lang_Thread::is_alive(oop java_thread) {
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  return (thr != NULL);
}

可以看到是通过Thread的eetop找到内部的JavaThread, 如果为NULL,则表示线程已死;
好,第一个问题得到解决,接下来看第二个问题:

在前面的文章Java线程源码解析之start的最后,说到

当run方法执行结束,会调用JavaThread::exit方法清理资源

//由于原方法较长,删除不相关部分
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
  ensure_join(this);
  assert(!this->has_pending_exception(), "ensure_join 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);
}

static void ensure_join(JavaThread* thread) {
  // 获取Threads_lock
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  ObjectLocker lock(threadObj, thread);
  // 忽略pending exception (ThreadDeath)
  thread->clear_pending_exception();
  //设置java.lang.Thread的threadStatus为 TERMINATED.
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
  //清除native线程,这将会导致isAlive()方法返回false 
  java_lang_Thread::set_thread(threadObj(), NULL);
 //通知所有等待thread锁的线程, join的wait方法将返回,由于isActive返回false,join方法将执行结束并返回
  lock.notify_all(thread);
}

从上面的源码实现知道,当run方法执行结束,会将native线程对象设为null,并且通过notifyAll方法,让等待在Thread对象锁上的wait方法返回;因此Thread.join常用于等待线程执行完毕,当然如果中间出现异常,join方法也会返回。

你可能感兴趣的:(Java线程源码解析之join)