本文主要是想測試 threadLoop 線程是不是循環執行。
1. ThreadTest.cpp
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/threads.h>
namespace android {
class ThreadTest : public Thread {
virtual bool threadLoop();
};
bool ThreadTest::threadLoop() {
printf("threadLoop\n");
sleep(1);
return true;
}
}
using namespace android;
int main() {
sp<ThreadTest> thr = new ThreadTest();
thr->run();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
2. Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS:= optional
LOCAL_SRC_FILES := \
ThreadTest.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder
LOCAL_MODULE := ThreadTest
include $(BUILD_EXECUTABLE)
3. 執行
可以看到每隔1秒,打印一次threadLoop,所以threadLoop是循環執行。
若用指針代替android的sp,即StrongPointer,則只打印一次threadLoop。如下所示:
//sp<ThreadTest> thr = new ThreadTest();
ThreadTest *thr = new ThreadTest();
或者在threadLoop函數中return false,也只打印一次threadLoop。
原因是Thread類的實現中,
先由pthreads或win32_threads實現創建thread,並將線程入口設爲_threadLoop。
_threadLoop再調用thread類實現者(ThreadTest)的threadLoop,並將這個threadLoop
放在do-while循環中,只有當threadLoop返回false或線程對象指針不是sp實現時,會退出循環。
_threadLoop示意代碼:
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user);
sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear();
#ifdef HAVE_ANDROID_OS
// this is very useful for debugging with gdb
self->mTid = gettid();
#endif
bool first = true;
do {
bool result;
if (first) {
first = false;
self->mStatus = self->readyToRun();
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
// running at least once after a successful ::readyToRun()
// (unless, of course, the thread has already been asked to exit
// at that point).
// This is because threads are essentially used like this:
// (new ThreadSubclass())->run();
// The caller therefore does not retain a strong reference to
// the thread and the thread would simply disappear after the
// successful ::readyToRun() call instead of entering the
// threadLoop at least once.
result = self->threadLoop();
}
} else {
result = self->threadLoop();
}
// establish a scope for mLock
{
Mutex::Autolock _l(self->mLock);
if (result == false || self->mExitPending) {
self->mExitPending = true;
self->mRunning = false;
// clear thread ID so that requestExitAndWait() does not exit if
// called by a new thread using the same thread ID as this one.
self->mThread = thread_id_t(-1);
// note that interested observers blocked in requestExitAndWait are
// awoken by broadcast, but blocked on mLock until break exits scope
self->mThreadExitedCondition.broadcast();
break;
}
}
// Release our strong reference, to let a chance to the thread
// to die a peaceful death.
strong.clear();
// And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != 0);
return 0;
}
關於sp,wp,可參考: