RunLoop与线程

作者: 我的梦想之路 | 来源:发表于2016-06-15 21:02 被阅读287次

    知识点

    1.每条线程都有唯一的一个与之对应的RunLoop对象
    2.主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
    3.RunLoop在第一次获取时创建,在线程结束时销毁

    查看CFRunLoopRef源文件

    #贴的是创建主线程的RunLoop(看中文注释的地方就好了)
    static CFMutableDictionaryRef __CFRunLoops = NULL;
    static CFLock_t loopsLock = CFLockInit;
    // should only be called by Foundation
    // t==0 is a synonym for "main thread" that always works
    CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
       if (pthread_equal(t, kNilPthreadT)) {
        t = pthread_main_thread_np();
         }
         __CFLock(&loopsLock);
       if (!__CFRunLoops) { 
            __CFUnlock(&loopsLock); 
            //创建字典         
            CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
            //创建主线程
        CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());    
            //保存主线程
             CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);
           if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
               CFRelease(dict);
        }   
          CFRelease(mainLoop);     
          __CFLock(&loopsLock);
       }
      //从字典中获取子线程的runloop
       CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
       __CFUnlock(&loopsLock); 
       if (!loop) {
        //如果子线程的runloop不存在,那么就为该线程创建一个对应的runloop    
        CFRunLoopRef newLoop = __CFRunLoopCreate(t); 
        __CFLock(&loopsLock);
        loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
         if (!loop) {
            //把当前子线程和对应的runloop保存到字典中   
             CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
            loop = newLoop; 
          } 
        // don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it 
        __CFUnlock(&loopsLock);
        CFRelease(newLoop); 
      } 
      if (pthread_equal(t, pthread_self())) {
         _CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL);
          if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) { 
            _CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop); 
          } 
        } 
      return loop;
      }
    // should only be called by Foundation
    CFRunLoopRef _CFRunLoopGet0b(pthread_t t) {
         if (pthread_equal(t, kNilPthreadT)) {
        t = pthread_main_thread_np();
         } 
          __CFLock(&loopsLock);
         CFRunLoopRef loop = NULL;
         if (__CFRunLoops) {
             loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
          } 
        __CFUnlock(&loopsLock);
       return loop;
      }
    #注意:runloop和线程是一一对应的
    

    获取RunLoop对象

    #Foundation框架中
     //获取当前线程的runloop对象
    NSRunLoop  *currentRunloop = [NSRunLoop currentRunLoop];
    //获取主线程的runloop对象
    NSRunLoop  *mainRunloop = [NSRunLoop mainRunLoop]; 
    
    #CFRunLoopRef(因为是C语言的,所以直接调用函数即可获取)
    
    CFRunLoopRef runloop1 = CFRunLoopGetCurrent();
    
    CFRunLoopRef runloop2 = CFRunLoopGetMain();
    
    #NSRunLoop --->转换为 CFRunLoopRef
    CFRunLoopRef runloop3 = currentRunloop.getCFRunLoop;
    
    获取runloop输出日志(很多东西,看不懂)

    创建子线程的RunLoop

    // 创建一个线程
    NSThred *thread = [[NSTread alloc] init@ithTarget:self selector:@selector(show) object:nil];
     // 启动线程
      [thread start];
    
    - (void)show{
      NSLog(@"--%@--",[NSRunLoop currentRunLoop]);
    // [ [NSRunLoop alloc] init]; --->这个方法是无法获取到runloop对象
    //但是为什么有这个方法? 因为NSRunLoop是Object的子类,不能用,但是是存在这个方法的。
    #如何获取呢?
     // [NSRunLoop currentRunLoop];
    //懒加载的形式获取,不要忘记,我们是在这个方法里。取到的是当前的。
    }
    #这里的NSThread是会挂掉,不会持续运行的,因为NSRunLoop也会销毁。
    #如果想要知道如何持续运行,静待下文了,说好一天一个的。不能贪多。
    

    RunLoop与线程的关系是一一对应的,要记住这一点。

    相关文章

      网友评论

        本文标题:RunLoop与线程

        本文链接:https://www.haomeiwen.com/subject/uojpdttx.html