在我们Linux系统中创建线程函数为:pthread_create(),在Android中我们为线程封装了一个类Thread,实际调用的还是pthread_create()
当我们想创建线程的时候,只需要继承于这个Thread类并实现虚函数thread_loop()即可。

frameworks/base/include/utils/threads.hclass Thread : virtual public RefBase{public:// 创建一个Thread对象,但是并不立即启动线程函数Thread(bool canCallJava = true);virtual ~Thread();// 开始启动线程函数,调用的是threadLoopvirtual 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()返回truebool exitPending() const;private:// 这是实际的线程函数,继承类必须实现它,// 返回true的话再次调用,返回false的话就会退出virtual bool threadLoop() = 0;// 禁止赋值Thread& operator = (const Thread&);// 内部类,被run函数调用,实际调用threadLoopstatic 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);elseres = 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()方法,启动函数

更多相关文章

  1. Hello Android(安卓)- 调用打电话和发短信及intent一些其他用法
  2. Android的IPC机制之Binder详细介绍
  3. Android实现多线程下载文件的方法
  4. android源码分析流程-init.c
  5. Android类参考---Fragment(七)
  6. android加载gif图片的动画库
  7. Cocos2d-x 新版本中android震动
  8. 由rxjava中Flowable注释,引出的Reactive-Streams相关知识
  9. android ANR 问题

随机推荐

  1. Android入门2—创建AVD
  2. Android命令monkey测试
  3. Android程序开发0基础教程(一)
  4. android模拟器管理和使用SD卡
  5. EditText设置更多文字为省略号
  6. Android Java调用ffmpeg命令
  7. android 播放默认铃声和手机振动
  8. Android自适应屏幕大小和layout布局
  9. Android世界:android 线程池
  10. Android ThreadLocal及InheritableThread