美文网首页
Java线程源码解析之join

Java线程源码解析之join

作者: allanYan | 来源:发表于2016-12-20 14:36 被阅读0次

    概述

    面试时,经常会有面试官会问到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

          本文链接:https://www.haomeiwen.com/subject/lioxvttx.html