第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

java線程的join方法源碼分析的不解問題

java線程的join方法源碼分析的不解問題

梵蒂岡之花 2019-03-13 10:15:39
1.首先通過源碼可以看到j(luò)oin方法的底層邏輯還是使用當(dāng)前線程對(duì)象的wait方法,也知道子線程執(zhí)行完業(yè)務(wù)代碼后,主線程才能解除阻塞。我認(rèn)為既然使用的是wait方法,必然需要notify或notifyAll來喚醒,但喚醒的機(jī)制是什么?難道使用的線程的隱式鉤子方式,當(dāng)線程執(zhí)行完后再進(jìn)行notify?2.偽代碼,按自己的理解實(shí)現(xiàn)join方法,不知道這樣對(duì)不對(duì)?public class JoinTest {public static void main(String[] args) throws InterruptedException {    ThreadTest tt=new ThreadTest();    tt.start();    synchronized (tt) {        tt.wait();    }    System.out.println("主線程繼續(xù)。。。。");}}class ThreadTest extends Thread {public void run() {    for(int i=0;i<5;i++){        try {            Thread.sleep(1000);            System.out.println("i="+i);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}}//---輸出結(jié)果輸下----i=0i=1i=2i=3i=4主線程繼續(xù)。。。。
查看完整描述

3 回答

?
繁星coding

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;

}


....


查看完整回答
反對(duì) 回復(fù) 2019-04-19
?
函數(shù)式編程

TA貢獻(xiàn)1807條經(jīng)驗(yàn) 獲得超9個(gè)贊

  1. 子線程執(zhí)行完畢之后,會(huì)調(diào)用exit()方法。
    exit()方法是線程執(zhí)行完畢之后,由系統(tǒng)自動(dòng)調(diào)用,可以看API介紹。

  2. exit()方法會(huì)調(diào)用notifyAll()。


查看完整回答
反對(duì) 回復(fù) 2019-04-19
  • 3 回答
  • 0 關(guān)注
  • 594 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)