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

  转自: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()方法,启动函数 
时间: 2024-10-10 07:13:44

Android开发之Thread类分析 (转载)的相关文章

Android开发之Html类详解

在进行Android开发中经常回忽略Html类.这个类其实很简单,就是将HTML标签文本解析成普通的样式文本.下面就让我么看一下这个类的具体介绍. 类结构: java.lang.Object    ? android.text.Html 类概述: 这个类用于处理的HTML字符串并将其转换成可显示的样式文本.但并不是所有的HTML标记的支持. 公有方法: 说其简单是应为它就有四个方法: Public Methods static String escapeHtml(CharSequence tex

Android开发之MediaRecorder类详解

MediaRecorder类详解 手机一般都有麦克风和摄像头,而Android系统就可以利用这些硬件来录制音视频了. 为了增加对录制音视频的支持,Android系统提供了一个MediaRecorder的类.该类的使用也非常简单,下面让我们来了解一下这个类: 一.类结构: java.lang.Object    ? android.media.MediaRecorder 二.类概述: 用于录制音频和视频的一个类. 三.状态图: 说明: 与MediaPlayer类非常相似MediaRecorder也

Android开发之Thread+Handler示例(打地鼠)

直接上代码 package com.mingrisoft; import java.util.Random; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.MotionEvent; import android.view.View; import android.view.View.On

Android开发之Tween(补间动画)完全解析(下)

欢迎转载,转载请注明出处:http://blog.csdn.net/dmk877/article/details/51980734 在上一篇文章中,我们详细讨论了Tween动画的xml的实现以及interpolator的使用,相信通过上篇文章大家对Tween动画的xml属性的配置会有一个详细的理解,当然这篇文章也是承接上篇文章,所以强烈建议先阅读上篇文章:Android开发之Tween(补间动画)完全解析(上),这篇文章将从代码的角度实现上篇文章的效果.如有疑问请留言,如有谬误欢迎批评指正. T

Android开发之InstanceState详解

Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceState(),并且在介绍这两个方法之后,再分别来实现使用InstanceState保存和恢复数据功能.Android实现屏幕旋转异步下载效果这样两个示例. 首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Andr

Android开发之InstanceState详解(转)---利用其保存Activity状态

Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceState(),并且在介绍这两个方法之后,再分别来实现使用InstanceState保存和恢复数据功能.Android实现屏幕旋转异步下载效果这样两个示例. 首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Andr

Android开发之JSON使用

Android开发之JSON使用 今天在论坛看到有不少朋友问关于json的问题,所以想写一篇关于android中使用json的博客. 首先 json是什么 JSON的全称是JavaScript Object Notation,从这里可以看到它源于JavaScript,它采用文本形式体现.比如 {"name":"zhangsan","age":20,"wife":"如花"} 这个简单表示了一个对象,在java

android开发之MediaPlayer+Service MP3播放器

http://blog.csdn.net/zzy916853616/article/details/6450753 [java] view plaincopy import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.List; import android.app.ListActivity; import android.apps.service.Player

Android开发之SQLite数据库详解

Android开发之SQLite数据库详解 请尊重他人的劳动成果,转载请注明出处:Android开发之SQLite数据库详解 http://blog.csdn.net/fengyuzhengfan/article/details/40194393 Android系统集成了一个轻量级的数据库:SQLite, SQLite并不想成为像Oracle.MySQL那样的专业数据库.SQLite只是一个嵌入式的数据库引擎,专门适用于资源有限的设备上(如手机.PDA等)适量数据存取. 虽然SQLite支持绝大