<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                Thread類雖說挺簡單,但它構造函數中的那個canCallJava卻一度使我感到費解。因為我一直使用的是自己封裝的Pthread類。當發現Thread構造函數中竟然存在這樣一個東西時,很擔心自己封裝的Pthread類會不會有什么重大問題,因為當時我還從來沒考慮過Java方面的問題。 ~~~ // canCallJava表示這個線程是否會使用JNI函數。為什么需要一個這樣的參數呢? Thread(bool canCallJava = true)。 ~~~ 我們必須得了解它實際創建的線程函數是什么。Thread類真實的線程是創建在run函數中的。 1. 一個變量,兩種處理 先來看一段代碼: **Thread.cpp** ~~~ status_t Thread::run(const char* name, int32_tpriority, size_t stack) { Mutex::Autolock_l(mLock); .... //如果mCanCallJava為真,則調用createThreadEtc函數,線程函數是_threadLoop。 //_threadLoop是Thread.cpp中定義的一個函數。 if(mCanCallJava) { res = createThreadEtc(_threadLoop,this, name, priority,stack,&mThread); } else{ res = androidCreateRawThreadEtc(_threadLoop, this, name, priority, stack,&mThread); } ~~~ 上面的mCanCallJava將線程創建函數的邏輯分為兩個分支,雖傳入的參數都有_threadLoop,但調用的函數卻不同。先直接看mCanCallJava為true的這個分支,代碼如下所示: **Thread.h::createThreadEtc()函數** ~~~ inline bool createThreadEtc(thread_func_tentryFunction, void *userData, const char*threadName = "android:unnamed_thread", int32_tthreadPriority = PRIORITY_DEFAULT, size_tthreadStackSize = 0, thread_id_t*threadId = 0) { returnandroidCreateThreadEtc(entryFunction, userData, threadName, threadPriority, threadStackSize,threadId) ? true : false; } ~~~ 它調用的是androidCreateThreadEtc函數,相關代碼如下所示: ~~~ // gCreateThreadFn是函數指針,初始化時和mCanCallJava為false時使用的是同一個 //線程創建函數。那么有地方會修改它嗎? static android_create_thread_fn gCreateThreadFn= androidCreateRawThreadEtc; int androidCreateThreadEtc(android_thread_func_tentryFunction, void*userData,const char* threadName, int32_tthreadPriority,size_t threadStackSize, android_thread_id_t*threadId) { returngCreateThreadFn(entryFunction, userData, threadName, threadPriority,threadStackSize, threadId); } ~~~ 如果沒有人修改這個函數指針,那么mCanCallJava就是虛晃一槍,并無什么作用,很可惜,代碼中有的地方是會修改這個函數指針的指向的,請看: 2. zygote偷梁換柱 在第四章4.2.1的第2小節AndroidRuntime調用startReg的地方,就有可能修改這個函數指針,其代碼如下所示: **AndroidRuntime.cpp** ~~~ /*static*/ int AndroidRuntime::startReg(JNIEnv*env) { //這里會修改函數指針為javaCreateThreadEtc androidSetCreateThreadFunc((android_create_thread_fn)javaCreateThreadEtc); return0; } ~~~ 所以,如果mCanCallJava為true,則將調用javaCreateThreadEtc。那么,這個函數有什么特殊之處呢?來看其代碼,如下所示: **AndroidRuntime.cpp** ~~~ int AndroidRuntime::javaCreateThreadEtc( android_thread_func_tentryFunction, void* userData, const char*threadName, int32_tthreadPriority, size_t threadStackSize, android_thread_id_t* threadId) { void**args = (void**) malloc(3 * sizeof(void*)); intresult; args[0] = (void*) entryFunction; args[1] = userData; args[2] = (void*) strdup(threadName); //調用的還是androidCreateRawThreadEtc,但線程函數卻換成了javaThreadShell。 result= androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args, threadName, threadPriority,threadStackSize, threadId); returnresult; } ~~~ **AndroidRuntime.cpp** ~~~ int AndroidRuntime::javaThreadShell(void* args){ ...... intresult; //把這個線程attach到JNI環境中,這樣這個線程就可以調用JNI的函數了 if(javaAttachThread(name, &env) != JNI_OK) return -1; //調用實際的線程函數干活 result = (*(android_thread_func_t)start)(userData); //從JNI環境中detach出來。 javaDetachThread(); free(name); returnresult; } ~~~ 3. 費力而討好 你明白mCanCallJava為true的目的了嗎?它創建的新線程將: - 在調用你的線程函數之前會attach到 JNI環境中,這樣,你的線程函數就可以無憂無慮地使用JNI函數了。 - 線程函數退出后,它會從JNI環境中detach,釋放一些資源。 第二點尤其重要,因為進程退出前,dalvik虛擬機會檢查是否有attach了,但是最后未detach的線程如果有,則會直接abort(這不是一件好事)。如果你關閉JNI check選項,就不會做這個檢查,但我覺得,這個檢查和資源釋放有關系。建議還是重視JNIcheck。如果直接使用POSIX的線程創建函數,那么凡是使用過attach的,最后就都需要detach! Android為了dalvik的健康真是費盡心機呀。 4. 線程函數_threadLoop介紹 不論一分為二是如何處理的,最終的線程函數_threadLoop都會被調用,為什么不直接調用用戶傳入的線程函數呢?莫非_threadLoop會有什么暗箱操作嗎?下面,我們來看: **Thread.cpp** ~~~ int Thread::_threadLoop(void* user) { Thread* const self = static_cast<Thread*>(user); sp<Thread> strong(self->mHoldSelf); wp<Thread> weak(strong); self->mHoldSelf.clear(); #if HAVE_ANDROID_OS self->mTid = gettid(); #endif boolfirst = true; do { bool result; if(first) { first = false; //self代表繼承Thread類的對象,第一次進來將調用readyToRun,看看是否準備好 self->mStatus = self->readyToRun(); result = (self->mStatus == NO_ERROR); if (result && !self->mExitPending) { result = self->threadLoop(); } }else { /* 調用子類實現的threadLoop函數,注意這段代碼運行在一個do-while循環中。 這表示即使我們的threadLoop返回了,線程也不一定會退出。 */ result = self->threadLoop(); } /* 線程退出的條件: 1)result 為false。這表明,如果子類在threadLoop中返回false,線程就可以 退出。這屬于主動退出的情況,是threadLoop自己不想繼續干活了,所以返回false。 讀者在自己的代碼中千萬別寫錯threadLoop的返回值。 2)mExitPending為true,這個變量可由Thread類的requestExit函數設置,這種 情況屬于被動退出,因為由外界強制設置了退出條件。 */ if(result == false || self->mExitPending) { self->mExitPending = true; self->mLock.lock(); self->mRunning = false; self->mThreadExitedCondition.broadcast(); self->mLock.unlock(); break; } strong.clear(); strong = weak.promote(); }while(strong != 0); return0; } ~~~ 關于_threadLoop,我們就介紹到這里。請讀者務必注意下面一點: - threadLoop運行在一個循環中,它的返回值可以決定是否退出線程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看