概述
面试时,经常会有面试官会问到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()方法等待;
那么:
- 如何判断线程是否活着呢?
- 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方法也会返回。
网友评论