码迷,mamicode.com
首页 > 移动开发 > 详细

Android开发之Thread类分析 (转载)

时间:2014-10-10 20:14:54      阅读:233      评论:0      收藏:0      [点我收藏+]

标签: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类分析 (转载)

标签:android   style   blog   http   color   io   使用   ar   java   

原文地址:http://www.cnblogs.com/lance-ehf/p/4016231.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!