6.2.5 秋风扫落叶——StartThread Pool和join Thread Pool分析
重要的内容都已讲过了,现在就剩下最后两个函数startThreadPool()和joinThreadPool没有分析了。它们太简单了,不是吗?
1.创造劳动力——startThreadPool()
startThreadPool()的实现,如下面的代码所示:
[—>ProcessState.cpp]
//太简单,没什么好说的。
void ProcessState:startThreadPool()
{
AutoMutex_l(mLock);
//如果已经startThreadPool的话,这个函数就没有什么实质作用了。
if(!mThreadPoolStarted){
mThreadPoolStarted=true;
spawnPooledThread(true);//注意,传进去的参数是true。
}
}
上面的spawnPooledThread()函数的实现如下所示:
[—>ProcessState.cpp]
void ProcessState:spawnPooledThread(bool isMain)
{
//注意,isMain参数是true。
if(mThreadPoolStarted){
int32_t s=android_atomic_add(1,&mThreadPoolSeq);
char buf[32];
sprintf(buf,"Binder Thread#%d",s);
sp<Thread>t=new PoolThread(isMain);
t->run(buf);
}
}
PoolThread是在IPCThreadState中定义的一个Thread子类,它的实现如下所示:
[—>IPCThreadState.h:PoolThread类]
class PoolThread:public Thread
{
public:
PoolThread(bool isMain)
:mIsMain(isMain){}
protected:
virtual bool threadLoop()
{
//线程函数如此简单,不过是在这个新线程中又创建了一个IPCThreadState。
//你还记得它是每个伙计都有一个的吗?
IPCThreadState:self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
2.万众归一——joinThreadPool
还需要看看IPCThreadState的joinThreadPool的实现,因为新创建的线程也会调用这个函数,具体代码如下所示:
[—>IPCThreadState.cpp]
void IPCThreadState:joinThreadPool(bool isMain)
{
//注意,如果isMain为true,我们则需要循环处理。把请求信息写到mOut中,待会儿一起发出去。
mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
androidSetThreadSchedulingGroup(mMyThreadId,ANDROID_TGROUP_DEFAULT);
status_t result;
do{
int32_t cmd;
if(mIn.dataPosition()>=mIn.dataSize()){
size_t numPending=mPendingWeakDerefs.size();
if(numPending>0){
for(size_t i=0;i<numPending;i++){
RefBase:weakref_type*refs=mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
//处理已经死亡的BBinder对象。
numPending=mPendingStrongDerefs.size();
if(numPending>0){
for(size_t i=0;i<numPending;i++){
BBinder*obj=mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
//发送命令,读取请求。
result=talkWithDriver();
if(result>=NO_ERROR){
size_t IN=mIn.dataAvail();
if(IN<sizeof(int32_t))continue;
cmd=mIn.readInt32();
result=executeCommand(cmd);//处理消息
}
……
}while(result!=-ECONNREFUSED&&result!=-EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
原来,我们的两个伙计在talkWithDriver,它们希望能从binder设备那里找到点可做的事情。
3.有几个线程在服务
到底有多少个线程在为Service服务呢?目前看来是两个:
startThreadPool中新启动的线程通过joinThreadPool读取binder设备,查看是否有请求。
主线程也调用joinThreadPool读取binder设备,查看是否有请求。看来,binder设备是支持多线程操作的,其中一定是做了同步方面的工作。
MediaServer这个进程一共注册了4个服务,繁忙的时候,两个线程会不会显得有点少呢?另外,如果实现的服务负担不是很重,完全可以不调用startThreadPool创建新的线程,使用主线程即可胜任。