在Android native(C++)层若想要创建一个线程则可以使用android平台native实现的Thread类来创建【当然你也可以直接使用C++标准库实现的std::thread,需引入头文件 #include,后续有时间再分析该标准库的实现】,而该类做了跨平台线程调用接口的处理和封装,具备了跨平台运行能力。
本系列文章分析的安卓源码版本:【Android 10.0 版本】
在此主要分析Android平台上的实现部分。
在native层使用该类必须引用android命名空间,因为该类是在android命名空间实现的,并引用该头文件【system/core/libutils/include/utils/Threads.h】,即可在自己的cpp文件中如下引用:
#include <utils/threads.h>
Threads.h文件内容如下:
// [system/core/libutils/include/utils/Threads.h]
#ifndef _LIBS_UTILS_THREADS_H
#define _LIBS_UTILS_THREADS_H
/*
* Please, DO NOT USE!
*
* This file is here only for legacy reasons. Instead, include directly
* the headers you need below.
*
*/
#include <utils/AndroidThreads.h>
// __cplusplus (C++)该宏定义的作用是:告诉C++编译器将这下面包含的头文件中的方法实现,
// 都按照C编译器的方式来处理编译,然后才能用于和C代码库相互链接。
// 可参考这篇文章很详细的介绍:【#ifdef __cplusplus 有什么作用】
// https://blog.csdn.net/thanklife/article/details/7362893
#ifdef __cplusplus
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <utils/Mutex.h>
#include <utils/RWLock.h>
#include <utils/Thread.h>
#endif
#endif // _LIBS_UTILS_THREADS_H
该头文件是一个线程功能集合体,提供了好几个头文件,其实若只是需要使用Thread线程类,我们不需要引用这么多头文件,因此正如文件中英文部分所指出的:
注意此处的英文注释的意思:意思就是最好不要再使用【threads.h】这个头文件,因为它是历史遗留原因造成的,相反,我们应该直接使用include下面所需的头文件即可,因此想用哪个头文件功能就直接引用它即可。
【另外主要区别就是:该threads.h头文件其实是用C编译器的方式编译代码的,因此在C++编程时不需要这么做】
因此可以更简单的头文件引入方式,如下:
只引入需要使用Thread线程类的头文件
#include <utils/Thread.h>
Thread类图:

Thread类声明:
声明的功能比较简单,类声明在android命名空间。
// [system/core/libutils/include/utils/Thread.h]
#ifndef _LIBS_UTILS_THREAD_H
#define _LIBS_UTILS_THREAD_H
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#if !defined(_WIN32)
# include <pthread.h>
#endif
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <utils/ThreadDefs.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
// 此处的英文表示,请不要使用该类,请使用std::thread类【C++标准库提供】来实现自己的线程,
// 应该是android自己实现的该类只提供给安卓native内部使用的吧。
// DO NOT USE: please use std::thread
// RefBase类是安卓智能指针的实现,此处不展开分析,可见后续相关分析章节
class Thread : virtual public RefBase
{
public:
// 显示调用构造函数
// explicit修饰符表示该类构造函数必须显示创建调用
// Create a Thread object, but doesn't create or start the associated
// thread. See the run() method.
explicit Thread(bool canCallJava = true);
virtual ~Thread();
// 启动线程运行
// 该方法可只传入线程名,其他两个参数为默认值
// priority:该参数表示当前线程的优先级别,主要用于CPU线程调用的处理
// 其取值范围常量定义在<utils/ThreadDefs.h>该头文件中
// stack:该参数表示线程大小
// Start the thread in threadLoop() which needs to be implemented.
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
// 请求退出线程
// 注意:英文注释表明,该方法被调用后,这个线程仍可能还正在运行,该方法可以在多线程中调用
// Ask this object's thread to exit. This function is asynchronous, when the
// function returns the thread might still be running. Of course, this
// function can be called from a different thread.
virtual void requestExit();
// 一次性初始化运行
// Good place to do one-time initializations
virtual status_t readyToRun();
// 请求退出并等待退出完毕后该方法才返回(调用端),
// 即该方法会阻塞调用端线程,直到彻底退出后才返回。
// 警告:必须小心调用该方法,避免造成死锁,即千万别在当前线程中调用该方法,否则会返回错误状态(WOULD_BLOCK)
// Call requestExit() and wait until this object's thread exits.
// BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
// this function from this object's thread. Will return WOULD_BLOCK in
// that case.
status_t requestExitAndWait();
// 等待线程(阻塞运行完毕),即该方法调用后会阻塞调用端线程,等待该线程执行完毕退出才返回调用端。
// 阻塞当前的(调用)线程,直到另外一个线程运行结束。
// 注意:若该线程未启动,则会立即返回。
// 警告:不要在该线程中调用该方法,否则会返回错误状态(WOULD_BLOCK)
// Wait until this object's thread exits. Returns immediately if not yet running.
// Do not call from this object's thread; will return WOULD_BLOCK in that case.
status_t join();
// 是否该线程正在运行
// Indicates whether this thread is running or not.
bool isRunning() const;
#if defined(__ANDROID__)
// 若存在安卓平台宏定义,则进入此处
// 返回该线程ID(线程内核ID)
// 注意:若该线程未启动则返回-1
// Return the thread's kernel ID, same as the thread itself calling gettid(),
// or -1 if the thread is not running.
pid_t getTid() const;
#endif
protected:
// 是否该线程已请求退出(正在退出或已退出完成状态)
// exitPending() returns true if requestExit() has been called.
bool exitPending() const;
private:
// 线程循环执行开始(方法)
// 重点:该方法就是子类需要实现的该线程中执行任务的方法,另外该线程的返回值有不同作用:
// 1)循环执行:若该方法返回true且未调用过requestExit()方法,则该方法将再次被调用执行即形成循环调用。
// 2)执行一次:若放回false,则该线程在该方法返回时将会退出。
// Derived class must implement threadLoop(). The thread starts its life
// here. There are two ways of using the Thread object:
// 1) loop: if threadLoop() returns true, it will be called again if
// requestExit() wasn't called.
// 2) once: if threadLoop() returns false, the thread will exit upon return.
virtual bool threadLoop() = 0;
private:
// 将赋值运算符= 函数放在此处声明的含义就是,不允许Thread线程类对象之间进行赋值
Thread& operator=(const Thread&);
// 线程循环方法(主要是用于线程启动时传入的方法引用【指针】)
static int _threadLoop(void* user);
// 是否可以调用Java
const bool mCanCallJava;
// 线程ID信息,读写都需要加锁
// always hold mLock when reading or writing
thread_id_t mThread;
// 互斥锁【主要此处使用了mutable关键字来修饰该变量】
// 备注:被mutable修饰的变量,可以突破const的限制,在被const修饰的函数里面也能被修改。
mutable Mutex mLock;
// 线程退出条件变量
Condition mThreadExitedCondition;
// 线程状态
status_t mStatus;
// 是否该线程已请求退出(正在退出或已退出完成状态)
// 备注:
// volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,
// 因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。
// 如果没有volatile关键字,则编译器可能优化读取和存储,可能暂

最低0.47元/天 解锁文章
980

被折叠的 条评论
为什么被折叠?



