RunLoop

2016-04-23  本文已影响0人  草水唐

RunLoop概述

一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的:
Event loop

RunLoop和Thread

一个RunLoop对应着一条唯一的线程

MainThread上的RunLoop默认是创建好并启动的,其它Thread中的RunLoop默认是没有创建RunLoop

在第一次获取时创建,在线程结束时销毁。除了MainThread外,其它Thread首次获取该Thread的RunLoop时才被创建,代码流程见下面

// 全局的 Dictionary ,key 是 pthread_t , value 是 CFRunLoopRef
static CFMutableDictionaryRef loopsDic;
// 访问 loopsDic 时的线程锁
static CFSpinLock_t loopsLock;

// 获取一个 pthread 对应的 RunLoop
CFRunLoopRef _CFRunLoopGet(pthread_t thread) {
    OSSpinLockLock(&loopsLock);

    if (!loopsDic) {
        // 第一次进入时,初始化全局 Dic ,并先为主线程创建一个RunLoop
        loopsDic = CFDictionaryCreateMutable();       
        CFRunLoopRef mainLoop = _CFRunLoopCreate();
        CFDictionarySetValue(loopsDic, pthread_main_thread_np(), mainLoop);  
    }

    // 直接从 Dictionary 里获取 thread
    CFRunLoopRef loop = CFDictionaryGetValue(loopsDis, thread);

    if (!loop) {
        // 如果取不到,创建一个
        loop = _CFRunLoopCreate();
        CFDictionarySetValue(loopsDic, thread, loop);
        // 注册一个回调,当线程销毁时,顺便也销毁其对应的 RunLoop
        _CFSetTSD(..., thread, loop, __CFFinalizeRunLoop);
    }

    OSSpinLockUnLock(&loopsLock); 
    return loop;
}

从上面的代码可以看出,线程和RunLoop之间是一一对应的,其关系是保存在一个全局的Dictionary里。线程刚创建时并没有RunLoop,如果你不主动获取,那它一直都不会被创建。RunLoop的创建是发生在第一次获取时,RunLoop的销毁是发生在线程结束时。只能在一个线程的内部获取其RunLoop(MainThread除外)。

注意:

上一篇下一篇

猜你喜欢

热点阅读