1. 程式人生 > >Android Thread之threadLoop方法——(追IMS原始碼時不知怎麼執行到threadLoop方法的,這篇文章有一個很好的解釋)

Android Thread之threadLoop方法——(追IMS原始碼時不知怎麼執行到threadLoop方法的,這篇文章有一個很好的解釋)

Android Framework中的執行緒Thread及它的threadLoop方法

在Framework中的Thread普遍的特點就是有一個 threadLoop方法。它到底是怎麼迴圈起來的。

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 stubsuper.handleMessage(msg);
        }
};

上面中通過mHandler傳送訊息就可以在mThread中處理了,並且這個mThread不是UIThread,不會阻塞主執行緒。

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;
    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");
    pthread_join(pId,NULL);
    printf("main thread  exit\n");

    return0;

}

然後編譯

gcc -o test test.c -lpthread./test

執行結果如下:

main thread running ,count : 0the pthread running ,count: 0
main thread running ,count : 1the pthread running ,count: 1
main thread running ,count : 2the pthread running ,count: 2
main thread running ,count : 3the pthread running ,count: 3
main thread running ,count : 4the pthread running ,count: 4
main thread will exit when pthread isoverthe pthread running ,count: 5the pthread running ,count: 6the 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.virtualvoid        
    requestExit();

    // FIXME merge API and implementation with AudioTrackThreadvoid            
    pause();        // suspend thread from execution at next loop boundaryvoid            
    resume();       // allow thread to execute, if not requested to exit
    // Where to store the dump, or NULL to not updatevoid            
    setDump(AudioWatchdogDump* dump);

private:
    virtual bool threadLoop();

    Mutex           mMyLock;        // Thread::mLock is private
    Condition       mMyCond;        // Thread::mThreadExitedCondition is privatebool            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 {

void AudioWatchdogDump::dump(int fd)
{
    char buf[32];
    if (mMostRecent != 0) {
        // includes NUL terminator
        ctime_r(&mMostRecent, buf);
    } else {
        strcpy(buf, "N/A\n");
    }
    fdprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s",
            mUnderruns, mLogs, buf);
}

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()returntrue;
        }
    }
    struct timespec newTs;
    int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
    if (rc != 0) {
        pause();
        returnfalse;
    }
    if (!mOldTsValid) {
        mOldTs = newTs;
        mOldTsValid = true;
        returntrue;
    }
    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();
        returnfalse;
    }
    returntrue;
}

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();
    }
}

void AudioWatchdog::setDump(AudioWatchdogDump *dump)
{
    mDump = dump != NULL ? dump : &mDummyDump;
}

}   // 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 mixerprivate:
                    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);
        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(    constchar* 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.virtualvoid        requestExit();

    // Good place to do one-time initializationsvirtual 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;
#endifprotected:
    // exitPending() returns trueifrequestExit() has been called.
            boolexitPending() 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&);
    staticint             _threadLoop(void* user);
    constbool            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 mLockvolatilebool           mExitPending;
    volatilebool           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, orin 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;
    }
#endifif (threadStackSize) {
        pthread_attr_setstacksize(&attr, threadStackSize);
    }

    errno = 0;
    pthread_t thread;
    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);
        return0;
    }

    ......
    return1;
}

刪除了不相關程式碼,大家看看是不是很熟悉啊。我在文章開始的部分就寫出了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 gdbself->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 scopeself->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);

    return0;
}

_threadLoop()這個方法就是Thread的最大祕密,它是一個while迴圈。 
1、建立執行緒時,會sp和wp一次執行緒本身。 
2、如果是第一次執行會執行執行緒的readyToRun()方法,再執行threadLoop(),否則,直接執行threadLoop()。 
3、threadLoop()方法有返回值,如果threadLoop()返回false的時候,執行緒會做清理工作,然後退出while迴圈,結束執行。

所以在這裡,我開始時的疑問—為什麼執行緒Thread中的threadLoop()能夠迴圈處理資料就到此做了說明。Thread被創 建,Thread中的run被呼叫,__threadLoop()被呼叫,readyToRun()被呼叫,然後迴圈呼叫threadLoop()。並且 在threadLoop()返回false時,可以退出迴圈。

特殊情況

有的時候Android Framework中Thread的run()方法很難發現在哪裡被呼叫。如SurfaceFlinger它也是一個Thread子類。在原始碼中搜索可以發現它的建立位置

class SurfaceFlinger : public BinderService<SurfaceFlinger>,
                       public BnSurfaceComposer,
                       private IBinder::DeathRecipient,
                       private Thread,
                       private HWComposer::EventHandler
{
public:
    staticcharconst* getServiceName() {
        return"SurfaceFlinger";
    }

    SurfaceFlinger();


    /* ------------------------------------------------------------------------
     * Thread interface
     */virtualbool threadLoop();
    virtual status_t readyToRun();
    virtualvoid 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();

但它本身並沒有實現instantiate()方法,那找它的父類。 
/frameworks/native/include/binder/BinderService.h

namespaceandroid {

template<typename SERVICE>
classBinderService
{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();
    }

    staticvoid 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...charvalue[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 
就看看sp吧。 
sp是Android在c++中搞得類似java中弱引用、強引用的一套指標概念,那應該是方便回收吧。 
而Android Framework中的c++世界,RefBase這個類有點像java中的Object. 
而sp是一個模板類。

總之呼叫sp時會呼叫SurfaceFlinger的onFirstRef()方法。 
那好,看程式碼吧

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);

    run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);

    // Wait for the main thread to be done with its initialization
    mReadyToRunBarrier.wait();
}

看見沒有?run()方法在這裡呼叫了。

所以,在Framework中如果你找不到一個Thread在何處被啟動,那麼去它的onFirstRef()方法中去看看吧

相關推薦

Android ThreadthreadLoop方法——IMS原始碼不知怎麼執行threadLoop方法文章一個解釋

Android Framework中的執行緒Thread及它的threadLoop方法 在Framework中的Thread普遍的特點就是有一個 threadLoop方法。它到底是怎麼迴圈起來的。 Android中java世界的Thread 先來看看java是怎麼建

Android介面回撥機制真相如果你一直接觸介面回撥但是自己又一直理解不了文章會讓你秒懂

本人自己也經常在開發中遇到介面回撥機制,說來慚愧,雖然一直在用介面,但是隻是去複製別人的程式碼,一直弄不明白介面回撥的原理,甚至自己也努力去看了很多篇文章,幾乎看了所有的介面回撥的例子,什麼延時問答啊,孔融讓梨啊,都看了,例子都能背下來了,兩三個月了還沒理解。看來本人頭腦不

如何快速入門python文章幫你指明方向零基礎的福音

一個 交流群 企業 小項目 調用 不錯 數據類型 數據 入門 這是曾經在悟空問答回答的一個問題,後來效果還不錯,所以發出來,裏面結合了當年的學習經驗和一些行業老師的建議,希望幫助更多有興趣的人。(第三點福利) Python語言這幾年大火,在世界編程語言排行中Python也位

過載操作符cin cout 都在文章裡出現了 注意區別

// A code block #include “iostream” using namespace std; class Date { private: int year,month,day; public: Date(int a=0,int b=0,int c=0) { this-&g

關於深度學習中的注意力機制文章從例項到原理都幫你參透了系統重點看

最近兩年,注意力模型(Attention Model)被廣泛使用在自然語言處理、影象識別及語音識別等各種不同型別的深度學習任務中,是深度學習技術中最值得關注與深入瞭解的核心技術之一。 本文以機器翻譯為例,深入淺出地介紹了深度學習中注意力機制的原理及關鍵計算機制,同時也抽

演算法設計與分析上週第五週的寫錯標題才是真正的第六週

Merge k Sorted Lists 題目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example:

Android開發經驗】APP的快取檔案到底應該存在哪?看完文章你應該就自己清楚了

只要是需要進行聯網獲取資料的APP,那麼不管是版本更新,還是圖片快取,都會在本地產生快取檔案。那麼,這些快取檔案到底放在什地方合適呢?系統有沒有給我們提供建議的快取位置呢?不同的快取位置有什麼不同呢?今天這篇文章就是主要來說明這個問題的。     首先,我們要知道,在A

解決:百度編輯器UEditor怎麼將圖片儲存到圖片伺服器或者上傳到ftp伺服器的問題如果你正在用UE文章值得你看下

在使用百度編輯器ueditor的時候,怎麼將圖片儲存到另一個伺服器,或者上傳到ftp伺服器?這個問題,估計很多使用UE的人會遇到。而且我百度過,沒有找到這個問題的解決方案。那麼:本篇文章就很適合你了。因為本文解決了這個問題。 1.當你使用UEditor(以下簡稱UE)的

android深入設計模式托付模式

-h listen back != new 聚合 string static data- (一)托付模式簡單介紹 托付模式是主要的設計模式之中的一個。托付。即是讓還有一個對象幫你做事情。 更多的模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了托

Android開發布局文件裏實現OnClick事件關聯處理方法

intent dsm nbsp ext 關聯 you vertica findview 時間 一般監聽OnClickListener事件,我們都是通過Button button = (Button)findViewById(....); button.se

Android複習旅--ViewPager自動輪播條

算一算,已經很久都沒有更博文了,最近又是拍畢業照又是幫別人拍微電影,自己也搗鼓些專案,忙這忙那的,都沒什麼時間寫部落格記錄筆記了。 唉,說這麼多其實都是自己太懶了,為了讓自己不那麼內疚,只好找些藉口安慰安慰自己,哈哈~。 好久沒寫部落格了,嘮叨嘮叨。 最近的de

Android複習旅--ViewPager應用引導頁

對於ViewPager,相信大家都不陌生,ViewPager在應用中的使用頻率和ListView是有得一拼的。而ViewPager最常用於三個場景,分別是應用的新手引導頁,廣告輪播控制元件,和Fragment結合做應用內的標籤頁。 由於網上已經有很多關於ViewPager的博文了,寫

Android基礎資料儲存SharedPreference

Android資料持久化是說在斷電後資料不會丟失,而根據儲存位置和實現方式一般有3種方式,這裡說sharedpreferences: 一,sharedpreferences儲存 該種方式是在應用獨有目錄data/data/[packgename]/shared_prefs/下

Android學習動畫總結

寫在前面:本文是根據hencoder提供的教程寫的總結。HenCoder https://hencoder.com。        Android裡動畫可以分為兩類:Animation和Transition,其中Animation又可以分為View Animation和Pr

Android學習動畫總結

寫在前面:本文是根據hencoder提供的教程寫的總結。HenCoder https://hencoder.com。      關於ObjectAnimator可以用ofInt()來做整數的屬性動畫和ofFloat()來做小數的屬性動畫。當需要對其他型別的屬性來做動畫就需要

Android應用電量測試PowerTutor

一、首先來看看,官網上的一些說明吧。 PowerTutor官網連結 大概是說了以下幾點:     a、針對google手機的應用,可以顯示CPU、網路介面、顯示器、GPS接收機等主要系統元件所消耗的電量。     b、APP使用者可以

Android學習RecyclerView學習實現瀑布流式佈局

RecyclerView,大家可以通過匯入support-v7對其進行使用。  如果使用AndroidStudio開發, 需要在build.gradle中新增: compile 'com.android.support:appcompat-v7:24.2.1' com

Android開發裁切拍照+相簿影象並設定頭像小結

先看效果:                                                   再貼程式碼: 自定義選擇照片底部彈出對話方塊佈局: <?xml version="1.0" encoding="utf-8"?> <Re

Android繪圖Canvas變換6

1 Canvas 與螢幕 前面講解了Canvas的基本概念,Android繪圖之Canvas概念理解(5) , 對Canvas的概念進行了分析,但是沒有說明和螢幕的關係,Canvas不等於螢幕,螢幕不會動的,我們也無法對螢幕進行(平移,縮放等)操作,只能對Canvas進行操作,所以對

Android專案JSON解析3種解析技術詳解

前言: 在我寫部落格前再宣告一下,我希望轉載我文章的某某某記得註明:(),要尊重我的勞動成果,這樣才能給我更多的支援和鼓勵!差不多有3天沒有寫部落格了,要想的、要做的事情太多了,額....原歸正傳,今天接著上一篇部落格:Android專案之JSON解析(扯淡),繼續分享我對