先看下Thread類中之前沒有太多關(guān)注的類定義:
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
/**
* The synchronization object responsible for this thread's join/sleep/park operations.
*/
private final Object lock = new Object();
private volatile long nativePeer;
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
public final void join(long millis) throws InterruptedException {
synchronized(lock) {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
lock.wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
lock.wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
join
從上面看到實(shí)際上檢測(cè)isAlive,因此線程未開始執(zhí)行時(shí)宙暇,是不生效的暴匠;
關(guān)鍵點(diǎn)調(diào)用了lock.wait函數(shù)精耐,那么在哪里notifyAll()呢希太?
在線程將要退出的時(shí)候克饶,要查看jvm中的實(shí)現(xiàn)
ensure_join方法中,調(diào)用 lock.notify_all(thread); 喚醒所有等待thread鎖的線程誊辉。
void JavaThread::run() {
...
thread_main_inner();
}
void JavaThread::thread_main_inner() {
...
this->exit(false);
delete this;
}
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
...
// 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);
...
}
static void ensure_join(JavaThread* thread) {
// We do not need to grap the Threads_lock, since we are operating on ourself.
Handle threadObj(thread, thread->threadObj());
assert(threadObj.not_null(), "java thread object must exist");
ObjectLocker lock(threadObj, thread);
// Ignore pending exception (ThreadDeath), since we are exiting anyway
thread->clear_pending_exception();
// Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED.
java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
// Clear the native thread instance - this makes isAlive return false and allows the join()
// to complete once we've done the notify_all below
java_lang_Thread::set_thread(threadObj(), NULL);
lock.notify_all(thread);
// Ignore pending exception (ThreadDeath), since we are exiting anyway
thread->clear_pending_exception();
}
final線程安全
而final可以防止此類事情的發(fā)生:如果某個(gè)成員是final的矾湃,JVM規(guī)范做出如下明確的保證:一旦對(duì)象引用對(duì)其他線程可見,則其final成員也必須正確的賦值了堕澄。