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创建新的线程,使用主线程即可胜任。