3 回答

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超4個(gè)贊
上邊已經(jīng)回答你的問題,線程結(jié)束時(shí)會(huì)調(diào)用notifyAll。
JVM底層實(shí)際是使用OS層提供的API來支持線程的,比如UNIX-Like的OS中一般使用pthread(Windows也有Pthread的實(shí)現(xiàn)),openjdk的hotspotVM使用的就是pthread,我們來看一下openjdk8版本的hotspotVM底層實(shí)際代碼。
在Thread執(zhí)行start的方法時(shí),就會(huì)調(diào)用native方法的start0,start0底層實(shí)際經(jīng)過很多層的封裝,最終會(huì)調(diào)用createJavaThread的方法,createJavaThread就會(huì)調(diào)pthread_create創(chuàng)建一個(gè)線程并執(zhí)行。
過程大致是這樣的:Thread.start() -> start0() -> ... -> createJavaCreate() -> pthread_create() => threadStart() => attachThread() -> 執(zhí)行Thread的run() -> detachThread() "這個(gè)方法最后會(huì)調(diào)用Object.notifyAll"。
openjdk-8-8u66-b17/jamvm-2.0.0/src/thread.c
void createJavaThread(Object *jThread, long long stack_size) {
Thread *self = threadSelf();
ExecEnv *ee = sysMalloc(sizeof(ExecEnv));
Thread *thread = sysMalloc(sizeof(Thread));
memset(ee, 0, sizeof(ExecEnv));
memset(thread, 0, sizeof(Thread));
thread->ee = ee;
ee->thread = jThread;
ee->stack_size = stack_size;
if(!classlibCreateJavaThread(thread, jThread)) {
sysFree(thread);
sysFree(ee);
return;
}
disableSuspend(self);
if(pthread_create(&thread->tid, &attributes, threadStart, thread)) {
classlibMarkThreadTerminated(jThread);
sysFree(ee);
enableSuspend(self);
signalException(java_lang_OutOfMemoryError, "can't create thread");
return;
}
pthread_mutex_lock(&lock);
/* Wait for thread to start */
while(classlibGetThreadState(thread) == CREATING)
pthread_cond_wait(&cv, &lock);
pthread_mutex_unlock(&lock);
enableSuspend(self);
}
....
void *threadStart(void *arg) {
Thread *thread = (Thread *)arg;
Object *jThread = thread->ee->thread;
/* Parent thread created thread with suspension disabled.
This is inherited so we need to enable */
enableSuspend(thread);
/* Complete initialisation of the thread structure, create the thread
stack and add the thread to the thread list */
initThread(thread, INST_DATA(jThread, int, daemon_offset), &thread);
/* Add thread to thread ID map hash table. */
addThreadToHash(thread);
/* Set state to running and notify creating thread */
signalThreadRunning(thread);
/* Execute the thread's run method */
executeMethod(jThread, CLASS_CB(jThread->class)->method_table[run_mtbl_idx]);
/* Run has completed. Detach the thread from the VM and exit */
detachThread(thread);
TRACE("Thread %p id: %d exited\n", thread, thread->id);
return NULL;
}
void *detachThread(Thread *thread) {
Object *keep_alive;
ExecEnv *ee = thread->ee;
Object *java_thread = ee->thread;
Object *group = INST_DATA(java_thread, Object*, group_offset);
/* If there's an exception pending, it is uncaught */
if(exceptionOccurred0(ee))
uncaughtException();
/* Don't do anything if this is the main thread */
if(thread->prev == NULL)
return NULL;
/* remove thread from thread group */
executeMethod(group, (CLASS_CB(group->class))->
method_table[rmveThrd_mtbl_idx], java_thread);
/* Remove thread from the ID map hash table */
deleteThreadFromHash(thread);
objectLock(java_thread);
/* Mark the thread as terminated. This state is used in determining
if the thread is alive and so must be done before notifying joining
threads. The VM thread structure is tied to a Java-level object
(see comment below). The keep_alive is an object which must be
kept alive to prevent the structure from being freed while we are
still accessing it */
keep_alive = classlibMarkThreadTerminated(java_thread);
/* Notify any threads waiting on the thread object -
these are joining this thread 這里調(diào)用objectNotifyAll */
objectNotifyAll(java_thread);
objectUnlock(java_thread);
/* Thread's about to die, so no need to enable suspend
afterwards. */
disableSuspend(thread);
/* Grab global lock, and update thread structures protected by
it (thread list, thread ID and number of daemon threads) */
pthread_mutex_lock(&lock);
/* It is safe to free the thread's ExecEnv and stack now as these are
only used within the thread. It is _not_ safe to free the native
thread structure as another thread may be concurrently accessing it.
However, they must have a reference to the java level thread --
therefore, it is safe to free during GC when the thread is determined
to be no longer reachable. */
sysFree(ee->stack);
sysFree(ee);
/* If no more daemon threads notify the main thread (which
may be waiting to exit VM). Note, this is not protected
by lock, but main thread checks again */
if(non_daemon_thrds == 0) {
/* No need to bother with disabling suspension
around lock, as we're no longer on thread list */
pthread_mutex_lock(&exit_lock);
pthread_cond_signal(&exit_cv);
pthread_mutex_unlock(&exit_lock);
}
/* Finally, clear the thread local data */
setThreadSelf(NULL);
TRACE("Thread %p id: %d detached from VM\n", thread, thread->id);
return keep_alive;
}
....

TA貢獻(xiàn)1807條經(jīng)驗(yàn) 獲得超9個(gè)贊
子線程執(zhí)行完畢之后,會(huì)調(diào)用
exit()
方法。exit()
方法是線程執(zhí)行完畢之后,由系統(tǒng)自動(dòng)調(diào)用,可以看API介紹。exit()
方法會(huì)調(diào)用notifyAll()
。
添加回答
舉報(bào)