精华内容
下载资源
问答
  • java Thread中,run方法和start方法的区别,下面说法错误的是? A通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。 B他们都可以实现了多线程运行。 Crun方法是thread的...

    java Thread中,run方法和start方法的区别,下面说法错误的是?

    A通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。
    B他们都可以实现了多线程运行。
    Crun方法是thread的一个普通方法调用。
    D调用start方法后,一旦得到cpu时间片,就开始执行run()方法。

    正确答案:B

     

    解析:

    start方法真正的实现了多线程,调用后此线程处于就绪状态,并没有运行,一旦获得CPU时间片,就开始执行
    run()方法,无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程。
    run只是线程内重写的一个方法,如果直接调用run()方法的话,程序中只有主线程这一个线程,其程序执行路
    径只有一条,还是顺序执行,还是要等待run()执行完后执行下面的代码
    
    
    通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。获得CPU使用权才会执行。

     

    展开全文
  • 它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它到底是怎么循环起来的...

    当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了许许多多的Thread。它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它为什么能够循环,还有它到底是怎么循环起来的?

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

    上面中通过mHandler发送消息就可以在mThread中处理了,并且这个mThread不是UIThread,不会阻塞主线程。
    HandlerThread是一个好东西,在源码中处处可见,希望对此不熟悉的新手及时去学习下它的用法。

    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;
        //创建子线程,线程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循环。

    1、创建线程时,会sp和wp一次线程本身。
    2、如果是第一次执行会运行线程的readyToRun()方法,再执行threadLoop(),否则,直接运行threadLoop()。
    3、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();

    但它本身并没有实现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()方法中去看看吧

    展开全文
  • Android ThreadthreadLoop方法

    千次阅读 2018-04-12 17:27:54
    Android Framework的线程Thread及它的threadLoop方法 在FrameworkThread普遍的特点就是有一个 threadLoop方法。它到底是怎么循环起来的。 Androidjava世界的Thread 先来看看java是怎么创建一个线程的。...

    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()方法中去看看吧

    展开全文
  • 1. Thread的常用方法简介 2. Join()方法 3. Sleep() 方法:不会释放锁 4. Yield()方法:线程让步 不会释放锁 1. Thread的常用方法简介 首先,先看一下Thread的常见方法: 最主要的是区分其中...

    目录

    1. Thread类中的常用方法简介

    2. Join()方法

    3. Sleep() 方法:不会释放锁

    4. Yield()方法:线程让步  不会释放锁


    1. Thread类中的常用方法简介

    首先,先看一下Thread类中的常见方法:

    最主要的是区分其中join()、sleep()、yield()的用法区别

     

    2. Join()方法

    Thread的非静态方法join()让一个线程等待另外一个线程完成才继续执行。如果线程A执行体中调用B线程的join()方法,则A线程将会被阻塞,直到B线程执行完为止,A才能得以继续执行

    如下图:

    而且一定要理解“继续执行”的含义。比如有下面的三个线程:

    其中thread2线程执行了join()方法。也就是必须等thread2执行结束之后才能继续往下执行thread3。但是,在执行thread2的过程中可以执行thread1(往前执行线程)。这就是“继续执行”的含义。执行结果可以看一下:

    3. Sleep() 方法:不会释放锁

    Sleep——让当前正在执行的线程先暂停一定的时间,并进入阻塞状态。在其睡眠的时间段内,该线程由于不是处于就绪状态,因此不会得到执行的机会。即使此时系统中没有任何其他可执行的线程,处于sleep()中的线程也不会执行。因此sleep()方法常用来暂停线程的执行。当sleep()结束后,然后转入到 Runnable(就绪状态),这样才能够得到执行的机会。

     

    4. Yield()方法:线程让步  不会释放锁

    在第一节中已经介绍了,让一个线程执行了yield()方法后,就会进入Runnable(就绪状态),【不同于sleep()和join()方法,因为这两个方法是使线程进入阻塞状态】。除此之外,yield()方法还与线程优先级有关,当某个线程调用yield()方法时,就会从运行状态转换到就绪状态后,CPU从就绪状态线程队列中只会选择与该线程优先级相同或者更高优先级的线程去执行。

    展开全文
  • JAVA Thread Dump 的方法

    千次阅读 2011-11-29 12:00:41
    Thread Dump用来诊断Java应用的问题,可以用来查找内存泄露,发现死锁线程等等。通过它可以得到线程,线程运行状态、标识、调用的堆栈,堆栈包含完整的类名,所执行的方法,以及源代码所在的行数等等信息 使用方法...
  • Thread 的构造方法

    万次阅读 2014-07-08 19:26:28
    在Java创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。Thread类的...
  • java中Thread类的join()方法

    万次阅读 2012-03-10 11:45:47
    Thread有一个join()方法,在一个线程启动另外一个线程...下面我们新建两个继承Thread的类,让其中一个线程在另外一个线程调用join方法 class Thread1 extends Thread { public Thread1(String threadName) {
  • 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦...
  • Thread 类部分常用方法详解

    千次阅读 2020-09-29 23:25:21
    currentThread() 方法用来返回代码段正在被哪个线程调用,它是 Thread 类提供的一个 native 方法,返回一个 Thread 类的实例对象,源码如下: public static native Thread currentThread(); 废话就不多说了,直接...
  • threadstart()和run()方法的区别

    千次阅读 2019-04-12 11:08:21
    run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为...
  • 【Java】Thread的join()方法原理

    万次阅读 多人点赞 2018-05-09 18:34:09
    join()是Thread类的一个方法。根据jdk文档的定义: public final void join()throws InterruptedException: Waits for this thread to die. join()方法的作用,是等待这个线程结束;但显然,这样的定义并不清晰...
  • 其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。   interrupted()方法 作用是测试当前线程是否被中断...
  • java提供了两种线程方式,一种是继承java.lang包下的Thread类,覆写Thread类的run()方法,在run()方法中实现运行在线程上的代码!第二种是实现Runnable接口创建多线程。下面就跟大家具体的介绍一下这两种方式! 在...
  • 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。 在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡...
  • 在本教程,我们将讨论Thread的不同*join()*方法&nbsp;&nbsp;。我们将详细介绍这些方法和一些示例代码。 与&nbsp;&nbsp;wait()和notify()方法一样,*join()*是另一种线程间同步机制。 ...
  • Android 线程 thread 两种实现方法

    千次阅读 2015-09-27 22:03:49
    在android有两种实现线程thread方法: 一种是,扩展java.lang.Thread类  另一种是,实现Runnable接口   二: Thread类代表线程类,它的两个最主要的方法是:  run()——包含线程运行时所执行的...
  • 下面以pjsua_call_make_call为例说明: 如果执行pjsua_call_make_call的线程没有在pjsip注册过,就会assert中断,提示未知线程,需要使用pj_thread_register注册才可以 所以我们只要在线程先执行以下注册代码,...
  • Runnable是接口,我们可以通过实现Runnable接口来创建新的线程并启动。 new Thread(new MyRunnable()).start() run()方法它是Runnable接口的一个方法,我们可以通过它定义需要执行什么样的操作...下面是一个例子:
  • Thread 的join方法解释

    万次阅读 2018-09-03 12:39:50
     Thread的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。具体看代码:   public class JoinTest { public static void main(String [] args) throws InterruptedException { ...
  • Thread.Abort方法的误区

    千次阅读 2016-12-26 10:58:21
    大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Thread.Abort方法后线程就立刻停止了吗...
  • Thread类的几种常用方法

    万次阅读 2018-08-27 16:45:00
    2.run 此run非彼run (不是在run方法实现线程的逻辑,而是thread.run(),这个run方法是直接调用了线程的run) 3.yield(暂停当前线程,并执行其他线程) 4.sleep(使当前线程由运行状态变成阻塞状态,若睡眠时...
  • 保证Thread Safety的方法

    万次阅读 2019-06-24 21:44:36
    学习过多线程这一章之后,我觉得保护线程安全意义重大,做实验的时候会发现有时候一不小心就会发生死锁,今天来总结一下保证Thread Safety的几种方法。 在介绍之前,先了解一下多线程为什么会出现不安全的情况:...
  • Java Thread之Sleep()使用方法总结

    万次阅读 2018-11-12 17:19:45
    Thread.sleep()是Thread类的一个静态方法,使当前线程休眠,进入阻塞状态(暂停执行),如果线程在睡眠状态被中断,将会抛出IterruptedException中断异常。。主要方法如下: 【a】sleep(long millis) 线程睡眠 ...
  • Thread.join()方法解析

    万次阅读 2014-11-14 14:46:43
    Thread.join()方法解析
  • java中Thread用法

    万次阅读 2015-05-13 10:02:11
    上下文切换三.Thread方法线程的状态 在正式学习Thread的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread方法的理解。 线程从创建到最终的消亡,要经历若干个状态。...
  • C++11头文件thread的使用

    万次阅读 2017-06-17 22:56:04
    C++11加入了<thread>头文件,此头文件主要声明了std::thread线程类。C++11的标准类std::thread对线程...是C++标准程序库的一个头文件,定义了C++11标准的一些表示线程的类、用于互斥访问的类与方法等。 ...
  • android-Thread的run方法和start方法

    千次阅读 2015-05-14 08:43:30
    解说的很精辟,学习一下:Thread的run方法和start方法 1 线程的概念:线程的起动并不是简单的调用了RUN方法,而是由一个线程调度器来分别调用所有线程的RUN方法, 我们普通的RUN方法如果没有执行完是不会...
  • Thread类的run()和start()方法的区别

    万次阅读 2018-03-15 11:36:26
    start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。...
  • java Thread的start和run方法的区别

    千次阅读 多人点赞 2019-02-23 20:10:07
    t.start()会导致run()方法被调用,run()方法中的内容称为线程体,它就是这个线程需要执行的工作。 用start()来启动线程,实现了真正意义上的启动线程,此时会出现异步执行的效果,即在线程的创建和启动所述的随机...
  • ReactorThread和Scheduler

    万次阅读 热门讨论 2020-11-11 09:37:58
    今天我们要介绍的是Reactor的多线程模型和定时器模型,Reactor之前我们已经介绍过了,它实际上是观察者模式的延伸。 所以从本质上来说,Reactor是和多线程无关的。你可以把它用在多线程或者不用在多线程。 今天将...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 481,336
精华内容 192,534
关键字:

下面哪些方法是thread中的