知识点
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也会销毁。
#如果想要知道如何持续运行,静待下文了,说好一天一个的。不能贪多。
网友评论