Android中线程Thread源码解析

Android中线程Thread源码解析

一、Thread的介绍

Thread线程是进程中的独立运行的子任务。线程是CPU调度的最基本的单元,线程资源开销相对于进程而言比较小,所以我们一般是创建线程来执行任务。

1、Thread继承关系

Thread类实现了Runnable接口,且Thread类含有多个构造器进行重载

2、Thread线程状态

Thread线程主要有6种状态分别为:NEW(线程创建状态)、RUNNABLE(可运行状态)、BLOCKED(阻塞状态)、WAITING(等待状态)、TIMED_WAITING(计时等待状态)、TERMINATED(终止状态)

public enum State {
    NEW, //新创建,还未启动
    RUNNABLE,//可运行状态
    BLOCKED,//阻塞状态,等待同步锁的释放,如果获得锁就会自动进入运行状态
    WAITING,//等待状态, 需要被其他线程唤醒(notify,notifyAll的方法调用)
    TIMED_WAITING,//计时等待状态
    TERMINATED//被终止状态
}

Thread线程状态转化图:

3、线程名的设置

线程名的设置一般有两种方式,第一种就是通过Thread类构造器指定name参数,另一种就是通过setName方法指定;默认情况下是通过”Thread-“ + nextThreadNum()来指定

public static void main(String[] args) {
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
    thread1.setName("WorkerThread-1");//通过setName方法修改线程名,也可在构造器参数指定,默认是"Thread-" + nextThreadNum()
    thread1.start();
    System.out.println(Thread.currentThread().getName());//getName方法获取线程名
}

setName修改线程名源码分析:

public final synchronized void setName(String name) {
    checkAccess();//检查访问权限
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }

    this.name = name;
    if (threadStatus != 0) {
        setNativeName(name);//调用Native层方法设置线程名setNativeName
    }
}
private native void setNativeName(String name);

setNativeName映射对应JNI层的Thread.c文件

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},//setNativeName
};

然后继续转到jvm.cpp中的JVM_SetNativeThreadName方法

JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name))
  JVMWrapper("JVM_SetNativeThreadName");
  ResourceMark rm(THREAD);
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  if (Thread::current() == thr && !thr->has_attached_via_jni()) {
    const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
    //最后调用os中的set_native_thread_name方法
    os::set_native_thread_name(thread_name);
  }
JVM_END

最后,进入os中的set_native_thread_name方法

void os::set_native_thread_name(const char *name) {
#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
  if (name != NULL) {
    char buf[MAXTHREADNAMESIZE];
    snprintf(buf, sizeof(buf), "Java: %s", name);
    //调用POSIX线程标准库pthread库中的setname_np
    pthread_setname_np(buf);
  }
#endif
}

4、守护线程

守护线程顾名思义就是为其他线程服务的,比如JVM中的垃圾回收线程就是守护线程。

守护线程的特点:
  • 1、当守护的用户线程执行完毕了,JVM虚拟机退出,那么这个守护线程也就停止了。

  • 2、守护线程作为一个服务线程,如果服务的线程对象不存在了,那么这个守护线程也就没有存在的意义了。

守护线程的规则:
  • 1、在线程启动前设置为守护线程,通过setDaemon(boolean on)

  • 2、不要使用守护线程访问共享资源(数据库、文件等),因为它的生命周期随时都可能结束

  • 3、守护线程中产生的新线程也是守护线程

守护线程的使用:

将一个线程设置成守护线程很简单只需要调用thread.setDaemon(true)即可

5、线程的优先级

所谓线程优先级高仅仅是表示线程获取CPU时间片的几率高,但是这是不确定的因素

线程的优先级是高度依赖操作系统的,不同平台上都有所区别


/**
* 线程最低优先级 1
*/
public final static int MIN_PRIORITY = 1;

/**
* 线程默认优先级 5
*/
public final static int NORM_PRIORITY = 5;

/**
* 线程最高优先级 10
*/
public final static int MAX_PRIORITY = 10;

可以通过setPriority方法设置优先级:

 public final void setPriority(int newPriority) {
     ThreadGroup g;
     checkAccess();
     if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
         throw new IllegalArgumentException();
     }
     if((g = getThreadGroup()) != null) {
         if (newPriority > g.getMaxPriority()) {
             newPriority = g.getMaxPriority();
         }
         setPriority0(priority = newPriority);
     }
 }
 //setPriority0是Native方法
 private native void setPriority0(int newPriority);

setPriority0 JNI层方法

//Thread.c
static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},//对应映射到JVM_SetThreadPriority方法
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

//jvm.cpp
JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
  JVMWrapper("JVM_SetThreadPriority");
  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
  MutexLocker ml(Threads_lock);
  //通过jthread对象转换成java_thread的oop对象
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  //通过set_priority方法给java_thread设置优先级
  java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
  //再通过thread方法转化成JavaThread
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is
    Thread::set_priority(thr, (ThreadPriority)prio);//调用Thread中的set_priority方法设置优先级
  }
JVM_END

//thread.cpp
void Thread::set_priority(Thread* thread, ThreadPriority priority) {
  trace("set priority", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  // Can return an error!
  (void)os::set_priority(thread, priority);//最后调用os中的set_priority方法
}

//os_bsd.cpp
OSReturn os::set_native_priority(Thread* thread, int newpri) {
  if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK;

#ifdef __OpenBSD__
  // OpenBSD pthread_setprio starves low priority threads
  return OS_OK;
#elif defined(__FreeBSD__)
  int ret = pthread_setprio(thread->osthread()->pthread_id(), newpri);
#elif defined(__APPLE__) || defined(__NetBSD__)
  struct sched_param sp;
  int policy;
  pthread_t self = pthread_self();

  if (pthread_getschedparam(self, &policy, &sp) != 0)
    return OS_ERR;

  sp.sched_priority = newpri;
  if (pthread_setschedparam(self, policy, &sp) != 0)
    return OS_ERR;

  return OS_OK;
#else
  //setpriority设置优先级,分别设置PRIO_PROCESS进程,thread线程Id,优先级newpri
  int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri);
  return (ret == 0) ? OS_OK : OS_ERR;
#endif
}

二、Thread的基本使用

在Java中使用Thread线程方式主要有4种方法,分别是:Thread类+匿名类+重写run方法、Thread继承子类+重写run方法、Thread+Runnable匿名类+重写run方法、Thread+Runnable实现子类+重写run方法

1、Thread类+匿名类+重写run

public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread("Thread#1") {
            @Override
            public void run() {
                //todo sth
            }
        };
        thread.start();
    }
}

2、Thread继承子类+重写run

public class Test {
    static class UserThread extends Thread {
        public UserThread() {
            super("Thread#2");
        }

        @Override
        public void run() {
            //todo sth
        }
    }

    public static void main(String[] args) {
        UserThread thread = new UserThread();
        thread.start();
    }
}

3、Thread+Runnable匿名接口+重写run

public class Test {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //todo sth
            }
        },"Thread#3").start();
    }
}

4、Thread+Runnable实现子类+重写run

public class Test {
    static class TaskRunnable implements Runnable {
        @Override
        public void run() {
            //todo sth
        }
    }

    public static void main(String[] args) {
        new Thread(new TaskRunnable(), "Thread#4").start();
    }
}

5、Thread匿名类和Thread继承子类区别

方式 优点 缺点 应用场景
Thread继承子类 创建的线程类和对象可复用 使用复杂,代码量大 需要复用线程类和对象
Thread匿名类 使用简单 创建的线程类和对象不可复用 不需要复用线程类和对象

6、Runnable匿名接口和Runnable实现子类区别

方式 优点 缺点 应用场景
Thread+Runnable实现子类 功能扩展性好 使用复杂,代码量大 需要扩展多线程功能
Thread+Runnable匿名类 使用简单 功能扩展性差 不需要扩展多线程功能

7、继承Thread类与实现Runnable接口对比

三、Thread源码解析

1、Thread的构造器

在Java中线程Thread重载很多个构造器,总共有9个构造器进行重载。重载的参数主要有: name(线程名)、group(线程组)、target(Runnable对象)等

2、init方法分析

通过以上init源码分析,我们可以得到以下信息:

  • 一个线程的父线程parent, 就是该线程被创建时所处的线程,比如在主线程A中创建了新的线程B,那么B的parent就是线程A

  • 如果创建的新线程的parent是一个守护线程,那么这个新的线程也是守护线程;换句话说在守护线程内创建一个线程也是守护线程

  • 创建的新线程默认优先级为它的parent线程的优先级

  • 创建的新线程和它的parent线程处于同一个线程组

3、start方法具体实现分析

在Java中我们一般都是通过start方法来启动一个已创建的线程,那么start方法到底做了什么呢?

public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    //把当前的线程加入到线程组group中
    group.add(this);

    boolean started = false;
    try {
        //调用start0 Native方法 
        start0();
        started = true;//将线程启动状态置为true, 已启动
    } finally {
        try {
            if (!started) {//线程启动状态为false
                group.threadStartFailed(this);//需要交由它的线程组的threadStartFailed来处理
            }
        } catch (Throwable ignore) {

        }
    }
}

//定义的start0 native方法
private native void start0();

线程start调用的时候首先会把当前线程加入它的线程组列表中,然后线程组中未启动线程计数减1

//ThreadGroup中的add方法
//通知group线程组当前这个线程被启动了,以便于可以把它加入到线程组线程列表中,
//此外线程组中的未启动的线程数需要自减1
void add(Thread t) {
    synchronized (this) {
        if (destroyed) {
            throw new IllegalThreadStateException();
        }
        //threads是一个Thread的动态数组
        if (threads == null) {
            //默认开始是创建size为4的Thread数组
            threads = new Thread[4];
        } else if (nthreads == threads.length) {
            //之后默认扩容,扩大为当前线程数组长度的2倍
            threads = Arrays.copyOf(threads, nthreads * 2);
        }
        threads[nthreads] = t;//把启动线程的加入线程列表中,实际上加入到一个动态数组中

        //启动线程的计数累加1
        nthreads++;
        //未启动线程的计数累减1
        nUnstartedThreads--;
    }
}

对于start0线程启动失败的情况,会把它交给它的线程组group中的threadStartFailed方法来处理

void threadStartFailed(Thread t) {
     synchronized(this) {
         remove(t);//调用remove方法将启动失败线程从已启动线程列表中移除
         nUnstartedThreads++;//然后未启动线程计数累加1
     }
 }

 private void remove(Thread t) {
    synchronized (this) {
        if (destroyed) {
            return;
        }
        for (int i = 0 ; i < nthreads ; i++) {
            if (threads[i] == t) {
                System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
                threads[nthreads] = null;//回收启动失败线程在已启动线程列表中的位置
                break;
            }
        }
    }
}

然后我们进入核心方法start0Native方法来研究一下

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},//映射对应的方法JVM_StartThread
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

继续来看下jvm.cpp中的JVM_StartThread方法

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  //JavaThread的C++类定义的*native_thread对象
  JavaThread *native_thread = NULL;

  bool throw_illegal_thread_state = false;
  {
    //获取互斥锁
    MutexLocker mu(Threads_lock);
    //线程状态的检查,确保线程尚未启动
    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      throw_illegal_thread_state = true;
    } else {
      //通过stackSize获得堆栈的大小, 来分配C++的Thread对象内存大小
      jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
      //最后返回size_t无符号类型,所以需要避免负数的传递,size <= 0就直接返回0
      size_t sz = size > 0 ? (size_t) size : 0;
      //注意: 创建C++层的本地线程JavaThread对象,&thread_entry为Thread中的run方法入口,请参考下面thread_entry函数的介绍
      native_thread = new JavaThread(&thread_entry, sz);
      //检查本地线程是否包含OSThread, 因为可能出现因为内存不足导致OSThread创建失败
      if (native_thread->osthread() != NULL) {
        //准备JavaThread,链接Java线程对象到C++线程
        native_thread->prepare(jthread);
      }
    }
  }

  if (throw_illegal_thread_state) {
    THROW(vmSymbols::java_lang_IllegalThreadStateException());
  }

  assert(native_thread != NULL, "Starting null thread?");

  if (native_thread->osthread() == NULL) {
    // No one should hold a reference to the 'native_thread'.
    delete native_thread;
    if (JvmtiExport::should_post_resource_exhausted()) {
      JvmtiExport::post_resource_exhausted(
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
        "unable to create new native thread");
    }
    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
              "unable to create new native thread");
  }
  //启动JavaThread本地线程
  Thread::start(native_thread);

JVM_END

//&thread_entry是一个C++静态函数,它将作为JavaThread类构造函数的参数传入
static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
  Handle obj(THREAD, thread->threadObj());
  JavaValue result(T_VOID);
  JavaCalls::call_virtual(&result,
                          obj,
                          KlassHandle(THREAD, SystemDictionary::Thread_klass()),
                          vmSymbols::run_method_name(),
                          vmSymbols::void_method_signature(),
                          THREAD);
}

Thread.cpp中的JavaThread的构造器

//C++层的JavaThread类
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread()
#if INCLUDE_ALL_GCS
  , _satb_mark_queue(&_satb_mark_queue_set),
  _dirty_card_queue(&_dirty_card_queue_set)
#endif // INCLUDE_ALL_GCS
{
  if (TraceThreadEvents) {
    tty->print_cr("creating thread %p", this);
  }
  //初始化实例变量
  initialize();
  _jni_attach_state = _not_attaching_via_jni;
  //注意: 设置Java执行线程入口,最终会调用, 传进来的entry_point是thread_entry。这种方法会调用Thread.run方法。
  set_entry_point(entry_point);
  os::ThreadType thr_type = os::java_thread;
  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
                                                     os::java_thread;
  //通过os::create_thread创建一个OSThread
  os::create_thread(this, thr_type, stack_sz);
  _safepoint_visible = false;
}

再着进入os::create_thread方法

bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
  assert(thread->osthread() == NULL, "caller responsible");

  // 1、构造OSThread对象
  OSThread* osthread = new OSThread(NULL, NULL);
  if (osthread == NULL) {
    return false;
  }
  osthread->set_thread_type(thr_type);

  //2、将OSThread状态设置ALLOCATED状态
  osthread->set_state(ALLOCATED);

  //3、将OSThread和JavaThread关联
  thread->set_osthread(osthread);

  //4、初始化线程属性
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  // stack size
  ...

  ThreadState state;

  {
    pthread_t tid;
    //5、使用Posix中的Pthread库中的pthread_create创建本地子线程并且可执行
    //本地子线程运行java_start方法,JavaThread对象thread作为参数
    //pthread_create方法有四个参数: 
   //                         &tid(子程序返回的新线程的唯一标识)、
   //                         &attr(可用于设置线程属性,默认可为NULL)
   //                         java_start(线程创建后将执行传入的方法,java_start就是要执行的方法)
   //                         thread 是给java_start方法传入的参数对象,默认不传为NULL
    int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

    pthread_attr_destroy(&attr);

    if (ret != 0) {
      if (PrintMiscellaneous && (Verbose || WizardMode)) {
        perror("pthread_create()");
      }
      // Need to clean up stuff we've allocated so far
      thread->set_osthread(NULL);
      delete osthread;
      return false;
    }

    // Store pthread info into the OSThread
    osthread->set_pthread_id(tid);

    // 等待子线程初始化或中止
    {
      Monitor* sync_with_child = osthread->startThread_lock();
      MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
      while ((state = osthread->get_state()) == ALLOCATED) {
        sync_with_child->wait(Mutex::_no_safepoint_check_flag);
      }
    }

  }

  // Aborted due to thread limit being reached
  if (state == ZOMBIE) {
      thread->set_osthread(NULL);
      delete osthread;
      return false;
  }

  assert(state == INITIALIZED, "race condition");
  return true;
}

根据上述代码分析可知,会通过Posix库中pthread库中的pthread_create方法创建线程,然而传入第三个参数就是java_start,第四个参数thread就是作为java_start方法的参数,就是创建好线程后会执行该java_start方法,所以我们需要深入java_start方法。

//这里的*thread就是pthread_create方法中传入的第四个参数thread,作为java_start方法的参数
static void *java_start(Thread *thread) {
  static int counter = 0;
  //拿到进程ID
  int pid = os::current_process_id();
  alloca(((pid ^ counter++) & 7) * 128);
  //把thread对象存储到C++层中的ThreadLocalStorage
  ThreadLocalStorage::set_thread(thread);
  //创建OSThread对象
  OSThread* osthread = thread->osthread();
  Monitor* sync = osthread->startThread_lock();

  if (!_thread_safety_check(thread)) {
    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
    osthread->set_state(ZOMBIE);
    sync->notify_all();
    return NULL;
  }
  //设置osthread的线程ID
  osthread->set_thread_id(os::Bsd::gettid());

#ifdef __APPLE__
  uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
  guarantee(unique_thread_id != 0, "unique thread id was not found");
  osthread->set_unique_thread_id(unique_thread_id);
#endif
  os::Bsd::hotspot_sigmask(thread);
  os::Bsd::init_thread_fpu_state();

#ifdef __APPLE__
  if (objc_registerThreadWithCollectorFunction != NULL) {
    objc_registerThreadWithCollectorFunction();
  }
#endif

  // handshaking with parent thread
  {
    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);

    // 将OSThread从原来的ALLOCATED状态改变为INITIALIZED状态
    osthread->set_state(INITIALIZED);
    sync->notify_all();

    // 一直等待调用os::start_thread()方法来OSThread状态INITIALIZED改变,这样才会往下执行thread->run()
    while (osthread->get_state() == INITIALIZED) {
      sync->wait(Mutex::_no_safepoint_check_flag);
    }
  }

  // 调用JavaThread中的run方法
  thread->run();

  return 0;
}

上述都是JVM_StartThread方法中的new JavaThread(&thread_entry, sz)创建JavaThread对象过程,其中涉及到创建os::create_thread方法,然后再通过pthread_create创建真正本地线程,传入java_start要执行的方法。最后我们回到JVM_StartThread方法。

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;
  bool throw_illegal_thread_state = false;

  {
    MutexLocker mu(Threads_lock);
    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      throw_illegal_thread_state = true;
    } else {

      jlong size =
             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
      size_t sz = size > 0 ? (size_t) size : 0;
      native_thread = new JavaThread(&thread_entry, sz);
      if (native_thread->osthread() != NULL) {
        native_thread->prepare(jthread);
      }
    }
  }
  ...

  Thread::start(native_thread);//最后就是真正的Thread::start的方法

JVM_END

接着一起来看下Thread.cpp中的Thread::start方法

void Thread::start(Thread* thread) {
  trace("start", thread);
  if (!DisableStartThread) {
    if (thread->is_Java_thread()) {
      //设置线程状态为RUNNABLE
      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), java_lang_Thread::RUNNABLE);
    }
    //最后调用os中的start_thread方法
    os::start_thread(thread);
  }
}

然后一起来看下os.cpp中的start_thread方法

void os::start_thread(Thread* thread) {
  // guard suspend/resume
  MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
  //拿到JavaThread对象中的osThread对象
  OSThread* osthread = thread->osthread();
  //设置osThread对象为RUNNABLE状态,OSThread状态改变了,所以上述*java_start中的thread->run执行
  osthread->set_state(RUNNABLE);
  pd_start_thread(thread);
}

osThread状态由INITIALIZED变为了RUNNABLE状态后,*java_start中最后的thread->run()执行。

//这里的*thread就是pthread_create方法中传入的第四个参数thread,作为java_start方法的参数
static void *java_start(Thread *thread) {
   ...
  // handshaking with parent thread
  {
    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);

    // 将OSThread从原来的ALLOCATED状态改变为INITIALIZED状态
    osthread->set_state(INITIALIZED);
    sync->notify_all();

    // 等待调用os::start_thread()方法来OSThread状态改变,这样才会往下执行thread->run()
    while (osthread->get_state() == INITIALIZED) {
      sync->wait(Mutex::_no_safepoint_check_flag);
    }
  }

  // osThread状态由`INITIALIZED`变为了`RUNNABLE`状态,调用JavaThread中的run方法
  thread->run();
  return 0;
}

最后一起来看下JavaThread中的run方法

// The first routine called by a new Java thread
void JavaThread::run() {
  // 初始化操作...
  this->initialize_tlab();

   ...
  //最后调用thread_main_inner方法
  thread_main_inner();

  // Note, thread is no longer valid at this point!
}

接着看下thread_main_inner方法

void JavaThread::thread_main_inner() {
  assert(JavaThread::current() == this, "sanity check");
  assert(this->threadObj() != NULL, "just checking");

  //如果没有pending异常的话就会执行Thread entry point,
  if (!this->has_pending_exception() &&
      !java_lang_Thread::is_stillborn(this->threadObj())) {
    {
      ResourceMark rm(this);
      this->set_native_thread_name(this->get_thread_name());
    }
    HandleMark hm(this);
    //注意点: 还记得传入entry_point吗?一开始传入的是thread_entry, 也就是对应java.lang.Thread中的run,这样我们run就得以执行
    this->entry_point()(this, this);
  }

  DTRACE_THREAD_PROBE(stop, this);
  //执行清理工作
  this->exit(false);
  //销毁释放JavaThread对象
  delete this;
}

最后,我们知道entry_point实际上就是调用了jvm.cpp中的thread_entry方法

static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
  Handle obj(THREAD, thread->threadObj());
  JavaValue result(T_VOID);
  //注意这里实际上就是在调用java.lang.thread中的run方法,其中vmSymbols::run_method_name()对应的就是方法名"run"
  JavaCalls::call_virtual(&result,
                          obj,
                          KlassHandle(THREAD, SystemDictionary::Thread_klass()),
                          vmSymbols::run_method_name(),
                          vmSymbols::void_method_signature(),
                          THREAD);
}
//vmSysbols.hpp
 template(daemon_name,                               "daemon")        
 template(eetop_name,                                "eetop")         
 template(thread_status_name,                        "threadStatus")  
 template(run_method_name,                           "run")  //run方法         
 template(exit_method_name,                          "exit")          
 template(add_method_name,                           "add")           
 template(remove_method_name,                        "remove")        
 template(parent_name,                               "parent")  

4、start方法从Java层->JNI层->C++层->Java层的过程


   转载规则


《Android中线程Thread源码解析》 mikyou 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Android中的SparseArray源码解析 Android中的SparseArray源码解析
Android中的SparseArray源码解析一、概述 在Android平台中,更推荐使用SparseArray<E>来替代HashMap的数据结构,更具体的说,是用于替代key为int类型,value为Object类型的Ha
2019-12-29
下一篇 
Java中反射源码解析 Java中反射源码解析
Java中反射源码解析一、反射原理阐述1、从应用层角度 在JVM类型的编程语言中,任何一个编译好的类都会生成class文件, 在被类加载器加载完后都会有一个java.lang.Class<T>这个类Class实例对应。所以每个类
2019-12-29