当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了许许多多的Thread。它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它为什么能够循环,还有它到底是怎么循环起来的?
Android中java世界的Thread
我们先来看看java是怎么创建一个线程的。这个是最舒服的,也是我最熟悉的。
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
...
}
}).start();
当然,你也可以在android中创建一个消息循环的HandlerThread
HandlerThread mThread = new HandlerThread("test");
mThread.start();
Handler mHandler = new Handler(mThread.getLooper()){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
上面中通过mHandler发送消息就可以在mThread中处理了,并且这个mThread不是UIThread,不会阻塞主线程。
HandlerThread是一个好东西,在源码中处处可见,希望对此不熟悉的新手及时去学习下它的用法。
Linux下c语言的Thread
java世界的Thread很方便,那么c呢?
Android基于linux所以,多线程编程也应该基于linux下的多线程。linux下的c语言用pthread。大家可以看这篇文章。
linux下C/C++,多线程pthread
我把里面的例子改良了一下
test.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
//线程函数
void *test(void *ptr)
{
int i;
for(i=0;i<8;i++)
{
printf("the pthread running ,count: %d\n",i);
sleep(1);
}
}
int main(void)
{
pthread_t pId;
int i,ret;
//创建子线程,线程id为pId
ret = pthread_create(&pId,NULL,test,NULL);
if(ret != 0)
{
printf("create pthread error!\n");
exit(1);
}
for(i=0;i < 5;i++)
{
printf("main thread running ,count : %d\n",i);
sleep(1);
}
printf("main thread will exit when pthread is over\n");
//等待线程pId的完成
pthread_join(pId,NULL);
printf("main thread exit\n");
return 0;
}
然后编译
gcc -o test test.c -lpthread
./test
运行结果如下
main thread running ,count : 0
the pthread running ,count: 0
main thread running ,count : 1
the pthread running ,count: 1
main thread running ,count : 2
the pthread running ,count: 2
main thread running ,count : 3
the pthread running ,count: 3
main thread running ,count : 4
the pthread running ,count: 4
main thread will exit when pthread is over
the pthread running ,count: 5
the pthread running ,count: 6
the pthread running ,count: 7
main thread exit
例子比较简单,主要是创建一个线程,然后主线程等待子线程运行完毕再退出。
Android Framework中的Thread
下面焦点回到文章的主题当中,我们来看看Framework中常用的Thread是个何种形态。
先看看活生生的例子。
在源码中搜索threadLoop,当然也可以搜索thread,然后随便挑选一个Thread子类进行研究。这里挑选
/frameworks/av/services/audioflinger/AudioWatchdog.h
#ifndef AUDIO_WATCHDOG_H
#define AUDIO_WATCHDOG_H
#include <time.h>
#include <utils/Thread.h>
namespace android {
......
class AudioWatchdog : public Thread {
public:
AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
// mOldTs
// mLogTs initialized below
mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
{
#define MIN_TIME_BETWEEN_LOGS_SEC 60
// force an immediate log on first underrun
mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
mLogTs.tv_nsec = 0;
}
virtual ~AudioWatchdog() { }
// Do not call Thread::requestExitAndWait() without first calling requestExit().
// Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
virtual void requestExit();
// FIXME merge API and implementation with AudioTrackThread
void pause(); // suspend thread from execution at next loop boundary
void resume(); // allow thread to execute, if not requested to exit
// Where to store the dump, or NULL to not update
void setDump(AudioWatchdogDump* dump);
private:
virtual bool threadLoop();
Mutex mMyLock; // Thread::mLock is private
Condition mMyCond; // Thread::mThreadExitedCondition is private
bool mPaused; // whether thread is currently paused
......
};
} // namespace android
#endif // AUDIO_WATCHDOG_H
我们可以看到AudioWatchDog确实是Thread的子类,那好,下面看实现。
/frameworks/av/services/audioflinger/AudioWatchdog.cpp
#define LOG_TAG "AudioWatchdog"