Android開發之Thread類分析 (轉載)

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   io   使用   ar   java   

  轉自:http://blog.csdn.net/llping2011/article/details/9706599

 

       在我們Linux系統中建立線程函數為:pthread_create(),在Android中我們為線程封裝了一個類Thread,實際調用的還是pthread_create()
當我們想建立線程的時候,只需要繼承於這個Thread類並實現虛函數thread_loop()即可。

 

    frameworks/base/include/utils/threads.h      class Thread : virtual public RefBase      {      public:          // 建立一個Thread對象,但是並不立即啟動線程函數          Thread(bool canCallJava = true);          virtual ~Thread();          // 開始啟動線程函數,調用的是threadLoop          virtual status_t run(const char*name = 0, int32_t prority = PRIORITY_DEFAULT,                      size_t stack = 0);          // 申請退出這個線程          virtual void requestExit();          virtual status_t readyToRun();          // 調用requestExit()等待直到這個線程退出              status_t requestExitAndWait();          // 等待直到線程退出,如果沒有啟動立即返回              status_t join();      protected:          // 如果調用了requestExit()返回true          bool exitPending() const;      private:          // 這是實際的線程函數,繼承類必須實現它,          // 返回true的話再次調用,返回false的話就會退出          virtual bool threadLoop() = 0;          // 禁止賦值          Thread& operator = (const Thread&);          // 內部類,被run函數調用,實際調用threadLoop          static int _threadLoop(void* user);          const bool mCanCallJava;              thread_id_t mThread;    // thread_id_t 其實是 void*類型          mutable Mutex mLock;              Condition mThreadExitedCondition;              status_t mStatus;          // 注意:所以操作這兩個變數的地方都需要上鎖          volatile bool mExitPending;          volatile bool mRunning;              sp<Thread> mHoldSelf;      };  

 

我們首先看下Thread類的建構函式:

 

    Thread::Thread(bool canCallJava)           :   mCanCallJava(canCallJava),              mThread(thread_id_t(-1)),              mLock("Thrad::mLock"),              mStatus(NO_ERROR),              mExitPending(false), mRunnig(false)      {}  

 

真正啟動線程的函數:

    status_t Thread::run(const char*name, int32_t priority, size_t stack)      {          Mutex::Autolock _l(mLock);          if(mRunnig)              return INVALID_OPERATION;          mState = NO_ERROR;          mExitPending = false;          mThread = thread_id_t(-1);          mHoldSelf = this;   // 儲存著當前對象的引用          mRunning = true;          if (mCanCallJava)               res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread);          else              res = androidCreateRawThreadEtc(_threadLoop, this, name,                       priority, stack, &mThread);          if(res == false) {              mStatus = UNKNOWN_ERROR;              mRunning = false;              mThread = thread_id_t(-1);              mHoldSelf.clear();              return UNKNOWN_ERROR;          }          return NO_ERROR;      }      這裡有個判斷mCanCallJava是個什麼東西?接著往下看      inline bool createThreadEtc(thread_func_t entryFunction, void* userData,                  const char* threadName = "android:unnamed_thread",                  int32_t threadPriority = PRIORITY_DEFAULT,                  size_t threadStackSize = 0,                  thread_id_t *threadId = 0)      {          return androidCreateThreadEtc(entryFunction, userData, threadName, threadPriority,              threadStackSize, threadId) ? true : false;      }             int androidCreateThreadEtc(thread_func_t entryFunction,                   void* userData,                  const char* threadName,                  int32_t threadPriority = PRIORITY_DEFAULT,                  size_t threadStackSize = 0,                  thread_id_t *threadId = 0)      {          return gCreateThreadFn(entryFunction, userData, threadName, threadPriority,              threadStackSize, threadId);      }  

我們看到最後調用的是gCreateThreadFn這個函數,而gCreateThreadFn是個全域的函數指標,
static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
這裡預設給它賦值為 androidCreateRawThreadEtc,這跟前面調用的是一樣的???

既然是函數指標肯定有給它賦值的地方:

    void androidSetCreateThreadFunc(android_create_thread_fn func)      {          gCreateThreadFn = func;      }  

那這個函數在什麼地方調用的呢?又給它賦什麼值了呢?
我們找到了再AndroidRuntime類裡面啟動虛擬機器的地方:

    int androidRuntime::startReg(JNIEnv* env)      {          androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);          return 0;      }  

這樣如果我們的mCanCallJava如果為true的話,調用的就是:

    int AndroidRuntime::javaCreateThreadEtc(android_thread_func_t entryFunction,                      void* userData,                      const char* threadName,                      int32_t threadPriority,                      suze_t threadStackSize,                      android_thread_id_t *threadId)      {          void** args = (void**)malloc(3*sizeof(void*));          args[0] = (void*)entryFunction;          args[1] = userData;          args[2] = (void*)strdup(threadName);          return androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args.              threadName, threadPriority, threadStackSize, threadId);      }  

最後調用的還是同一個建立線程的函數只是回呼函數不一樣,這裡變成了AndroidRuntime::javaThreadShell

    int AndroidRuntime::javaCreateThreadEtc(void* args)      {          voir* start = ((void**)args)[0];          voir* userData = ((void**)args)[1];          voir* name = ((void**)args)[2];          free(args);          JNIEnv* env;                    javaAttachThread(name, &env);          result = (*(android_thead_func_t)start)(userData);          javaDetachThread();                    free(name);          return result;      }  

這裡線程函數javaThreadShell裡面還是調用前面我們的_threadLoop函數,只不過在調用之前,調用
了javaAttachThread()將線程attach到JNI環境中去了,這樣線程函數就可以調用JNI函數,最後線程
函數退出之後再調用javaDetachThread()退出JNI環境。

現在進入線程函數_threadLoop(),這是一個static函數

    int Thread::_threadLoop(void* user)      {          Thread* const self = static_cast<Thread*>(user);          sp<Thead> strong(self->mHoldSelf);          wp<Thead> weak(strong);          self->mHoldSelf.clear();                    bool first = true;                    do {    // 進入一個迴圈,通過判斷傳回值和內部退出標誌位決定是否退出線程              bool result;              if (fisr) {                  first = false;                  self->mStatus = self->readyToRun();                  result = (self->mStatus == NO_ERROR);                  if (result && !self->exitPendind()) {    // 檢查是否退出                      result = self->threadLoop(); // 調用實際線程函數                  }              } else {                  result = self->threadLoop();              }                            {                  Mutex::Autolock _l(self->mLock);                  if (result == false || self->mExitPending) {                      self->mExitPending = true;                      self-mRunning = false;                      self->mThread = thread_ir_t(-1);                      self->mThreadExitedCondition.broadcast();                      break;                  }                            }              strong.clear();              strong = weak.promote();          } while(strong != 0);          return 0;      }  

在這裡線程退出的條件為:
1)result = true 意味著子類在實現的threadLoop函數中返回false,這樣線程就主動退出了
2)mExidPendding = true 這個變數值由Thread類的requestExit函數設定,這樣線程就被動退出了。
最後如果線程退出了需要進行些去初始化操作,設定線程運行狀態,廣播告知其他關心這個線程的對象。

最後,如果我們想使用線程類:  1)建立一個類如MyThread,繼承與Thead類  2)在MyThread類中實現父類的純虛函數threadLoop,也就是我們調用pthread_create時傳入的線程函數。  3)定義一個MyThread變數 thread,調用線程的run()方法,啟動函數 

 

Android開發之Thread類分析 (轉載)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.