在Android Framework中的代碼看見了許許多多的Thread。它們廣泛的特色就是有一個threadLoop方法。按照字面的意思應該是這個線程可以循環處理數據。對應我想到到了java上層中的HandlerThread,這個估計也差很少,想弄清楚它爲何可以循環,還有它究竟是怎麼循環起來的?java
Android中java世界的Thread
咱們先來看看java是怎麼建立一個線程的。這個是最舒服的,也是我最熟悉的。linux
new Thread(new Runnable() {android
@Override
public void run() {
// TODO Auto-generated method stub
...
}
}).start();c++
固然,你也能夠在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);
}app
};less
上面中經過mHandler發送消息就能夠在mThread中處理了,而且這個mThread不是UIThread,不會阻塞主線程。
HandlerThread是一個好東西,在源碼中到處可見,但願對此不熟悉的新手及時去學習下它的用法。async
Linux下c語言的Thread
java世界的Thread很方便,那麼c呢?
Android基於linux因此,多線程編程也應該基於linux下的多線程。linux下的c語言用pthread。你們能夠看這篇文章。
linux下C/C++,多線程pthreadide
我把裏面的例子改良了一下
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"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include "AudioWatchdog.h"
namespace android {
bool AudioWatchdog::threadLoop()
{
{
AutoMutex _l(mMyLock);
if (mPaused) {
mMyCond.wait(mMyLock);
// ignore previous timestamp after resume()
mOldTsValid = false;
// force an immediate log on first underrun after resume()
mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
mLogTs.tv_nsec = 0;
// caller will check for exitPending()
return true;
}
}
struct timespec newTs;
int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
if (rc != 0) {
pause();
return false;
}
if (!mOldTsValid) {
mOldTs = newTs;
mOldTsValid = true;
return true;
}
time_t sec = newTs.tv_sec - mOldTs.tv_sec;
long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
if (nsec < 0) {
--sec;
nsec += 1000000000;
}
mOldTs = newTs;
// cycleNs is same as sec*1e9 + nsec, but limited to about 4 seconds
uint32_t cycleNs = nsec;
if (sec > 0) {
if (sec < 4) {
cycleNs += sec * 1000000000;
} else {
cycleNs = 4000000000u;
}
}
mLogTs.tv_sec += sec;
if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
mLogTs.tv_sec++;
mLogTs.tv_nsec -= 1000000000;
}
if (cycleNs > mMaxCycleNs) {
mDump->mUnderruns = ++mUnderruns;
if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
mDump->mLogs = ++mLogs;
mDump->mMostRecent = time(NULL);
ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
mLogTs.tv_sec = 0;
mLogTs.tv_nsec = 0;
}
}
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = mPeriodNs;
rc = nanosleep(&req, NULL);
if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
pause();
return false;
}
return true;
}
void AudioWatchdog::requestExit()
{
// must be in this order to avoid a race condition
Thread::requestExit();
resume();
}
void AudioWatchdog::pause()
{
AutoMutex _l(mMyLock);
mPaused = true;
}
void AudioWatchdog::resume()
{
AutoMutex _l(mMyLock);
if (mPaused) {
mPaused = false;
mMyCond.signal();
}
}
} // namespace android
很明顯,它的核心方法就是threadLoop(),在本文中咱們不關心它具體的功能,只想肯定它是怎麼啓動的呢?又是怎麼循環運行的呢?帶着疑問我又在源碼中搜索關鍵字AudioWatchdog
結果發現有兩個地方引用了。
/frameworks/av/services/audioflinger/AudioFlinger.h
/frameworks/av/services/audioflinger/AudioFlinger.cpp
在AudioFlinger.h中MixerThread中有個AudioWatchdog的sp對象
class MixerThread : public PlaybackThread {
public:
MixerThread (const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
audio_io_handle_t id,
audio_devices_t device,
type_t type = MIXER);
virtual ~MixerThread();
protected:
AudioMixer* mAudioMixer; // normal mixer
private:
sp<AudioWatchdog> mAudioWatchdog; // non-0 if there is an audio watchdog thread
};
咱們再看代碼
/frameworks/av/services/audioflinger/AudioFlinger.cpp
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, audio_devices_t device, type_t type)
: PlaybackThread(audioFlinger, output, id, device, type),
// mAudioMixer below
// mFastMixer below
mFastMixerFutex(0)
// mOutputSink below
// mPipeSink below
// mNormalSink below
{
......
#ifdef AUDIO_WATCHDOG
// create and start the watchdog
mAudioWatchdog = new AudioWatchdog();
mAudioWatchdog->setDump(&mAudioWatchdogDump);
//AudioWatchdog的run方法在此調用,因此線程啓動
mAudioWatchdog->run("AudioWatchdog", PRIORITY_URGENT_AUDIO);
tid = mAudioWatchdog->getTid();
err = requestPriority(getpid_cached, tid, kPriorityFastMixer);
if (err != 0) {
ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
kPriorityFastMixer, getpid_cached, tid, err);
}
#endif
......
}
刪掉不相關代碼,咱們看到AudioWatchdog對象確實建立了,而且調用了它的run方法。在java中Thread的run方法就是啓動,這個也應該如此。可是如以前的源碼所示AudioWatchdog.cpp中並無實現run方法,怎麼辦呢?別緊張,它還有父類Thread.
/frameworks/native/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(HAVE_PTHREADS)
# 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 {
// ---------------------------------------------------------------------------
class Thread : virtual public RefBase
{
public:
// Create a Thread object, but doesn't create or start the associated
// thread. See the run() method.
Thread(bool canCallJava = true);
virtual ~Thread();
// Start the thread in threadLoop() which needs to be implemented.
virtual status_t run( const char* name = 0,
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();
// 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();
// 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();
#ifdef HAVE_ANDROID_OS
// Return the thread's kernel ID, same as the thread itself calling gettid() or
// androidGetTid(), 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:
// 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& operator=(const Thread&);
static int _threadLoop(void* user);
const bool mCanCallJava;
// always hold mLock when reading or writing
thread_id_t mThread;
mutable Mutex mLock;
Condition mThreadExitedCondition;
status_t mStatus;
// note that all accesses of mExitPending and mRunning need to hold mLock
volatile bool mExitPending;
volatile bool mRunning;
sp<Thread> mHoldSelf;
#ifdef HAVE_ANDROID_OS
// legacy for debugging, not used by getTid() as it is set by the child thread
// and so is not initialized until the child reaches that point
pid_t mTid;
#endif
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // _LIBS_UTILS_THREAD_H
//
能夠看到確實有run方法。那下面看看它的實現
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
Mutex::Autolock _l(mLock);
if (mRunning) {
// thread already started
return INVALID_OPERATION;
}
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
mStatus = NO_ERROR;
mExitPending = false;
mThread = thread_id_t(-1);
// hold a strong reference on ourself
mHoldSelf = this;
mRunning = true;
bool res;
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
if (res == false) {
mStatus = UNKNOWN_ERROR; // something happened!
mRunning = false;
mThread = thread_id_t(-1);
mHoldSelf.clear(); // "this" may have gone away after this.
return UNKNOWN_ERROR;
}
// Do not refer to mStatus here: The thread is already running (may, in fact
// already have exited with a valid mStatus result). The NO_ERROR indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
return NO_ERROR;
// Exiting scope of mLock is a memory barrier and allows new thread to run
}
run()方法中有這麼一段
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
mCanCallJava的意思是能不能被JNI層調用,而後根據值去建立Thread,這裏有兩個分支,咱們就選擇createThreadEtc()
最終代碼會走到這裏
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
......
entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
userData = t;
}
#endif
if (threadStackSize) {
pthread_attr_setstacksize(&attr, threadStackSize);
}
errno = 0;
pthread_t thread;
//在此建立,文章開頭我有寫例子怎麼用c語言建立一個線程
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
pthread_attr_destroy(&attr);
if (result != 0) {
ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
"(android threadPriority=%d)",
entryFunction, result, errno, threadPriority);
return 0;
}
......
return 1;
}
刪除了不相關代碼,你們看看是否是很熟悉啊。我在文章開始的部分就寫出了linux下c語言pthread建立線程的例子,你們能夠回頭看看。也就是pthread_create()。這裏面傳進來的entryFunction是Thread中的_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.
//調用threadLoop()
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;
}
_threadLoop()這個方法就是Thread的最大祕密,它是一個while循環。
一、建立線程時,會sp和wp一次線程自己。
二、若是是第一次執行會運行線程的readyToRun()方法,再執行threadLoop(),不然,直接運行threadLoop()。
三、threadLoop()方法有返回值,若是threadLoop()返回false的時候,線程會作清理工做,而後退出while循環,結束運行。
因此在這裏,我開始時的疑問—爲何線程Thread中的threadLoop()可以循環處理數據就到此作了說明。
Thread被建立,
Thread中的run被調用,
__threadLoop()被調用,
readyToRun()被調用,
而後循環調用threadLoop()。
而且在threadLoop()返回false時,能夠退出循環。
!!!
!!!
還有,最關鍵的一點是threadLoop可以循環實際上是由於調用它的_threadLoop()方法裏面有一個while循環。
特殊狀況
有的時候Android Framework中Thread的run()方法很難發如今哪裏被調用。如SurfaceFlinger它也是一個Thread子類。在源碼中搜索能夠發現它的建立位置
class SurfaceFlinger : public BinderService<SurfaceFlinger>,
public BnSurfaceComposer,
private IBinder::DeathRecipient,
private Thread,
private HWComposer::EventHandler
{
public:
static char const* getServiceName() {
return "SurfaceFlinger";
}
SurfaceFlinger();
/* ------------------------------------------------------------------------
* Thread interface
*/
virtual bool threadLoop();
virtual status_t readyToRun();
virtual void onFirstRef();
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SURFACE_FLINGER_H
去找它建立的地方
/frameworks/base/cmds/system_server/library/system_init.cpp
extern "C" status_t system_init()
{
ALOGI("Entered system_init()");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p\n", sm.get());
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
ALOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
ALOGI("System server: starting Android services.\n");
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
return UNKNOWN_ERROR;
}
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
return UNKNOWN_ERROR;
}
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
ALOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("System server: exiting thread pool.\n");
return NO_ERROR;
}
咱們能夠看到
SurfaceFlinger::instantiate();
1
1
但它自己並無實現instantiate()方法,那之類找它的父類了。
/frameworks/native/include/binder/BinderService.h
namespace android {
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
}
static void publishAndJoinThreadPool(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() {
return NO_ERROR;
}
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_SERVICE_H
會調用publish()方法。
而SERVICE在這裏是一個模板類。在這裏SERVICE天然對應SurfaceFlinger
因此publish()會向ServiceManager添加一個Service這個Service就是Surfaceflinger。
而後咱們看SurfaceFlinger的構造函數
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionPending(false),
mAnimTransactionPending(false),
mLayersRemoved(false),
mRepaintEverything(0),
mBootTime(systemTime()),
mVisibleRegionsDirty(false),
mHwWorkListDirty(false),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false)
{
ALOGI("SurfaceFlinger is starting");
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
if (mDebugDDMS) {
if (!startDdmConnection()) {
// start failed, and DDMS debugging not enabled
mDebugDDMS = 0;
}
}
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
可是遺憾的是沒有發現run()方法的影蹤,沒有辦法只得去父類構造方法看
結果發現也沒有!!!
沒有辦法,繼續在源碼中搜索SurfaceFlinger,結果發現與之相關的信息大可能是sp<SurfaceFlinger>
就看看sp吧。
sp是Android在c++中搞得相似java中弱引用、強引用的一套指針概念,那應該是方便回收吧。
而Android Framework中的c++世界,RefBase這個類有點像java中的Object.
而sp是一個模板類。這部份內容,請看點擊下面連接
Android中的sp和wp指針
上面的連接講得還算詳細。這裏糾結sp的過多細節,長話短說,總之第一次對SurfaceFlinger引用調用sp<SurfaceFlinger>時會調用SurfaceFlinger的onFirstRef()方法。
那好,看代碼吧
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
//run方法在此被調用
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
// Wait for the main thread to be done with its initialization
mReadyToRunBarrier.wait();
}
看見沒有?run()方法在這裏調用了。
因此,在Framework中若是你找不到一個Thread在何處被啓動,那麼去它的onFirstRef()方法中去看看吧