最近写一些关于线程保活/取消的测试 具体代码以下bash
-(void)test {
for (int i = 0; i < 100000; ++i) {
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
[self performSelector:@selector(stopThread) onThread:thread withObject:nil waitUntilDone:YES];
}
}
-(void)stopThread {
CFRunLoopStop(CFRunLoopGetCurrent());
NSThread *thread = [NSThread currentThread];
[thread cancel];
}
-(void)run {
@autoreleasepool {
NSLog(@"current thread = %@", [NSThread currentThread]);
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
if (!port) {
port = [NSPort port];
}
[runLoop addPort:port forMode:NSDefaultRunLoopMode];
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
复制代码
关于 Runloop 的介绍我也不在此赘述。就说一下我遇到的问题. 在oop
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
复制代码
这句中,我尝试着使用了 NSRunLoopCommonModes
,来设定 Mode。就行 ruanloop 运行。 可是我会收到 Crash.测试
可是若是我使用 NSDefaultRunLoopMode
来填充这个 mode 就不会 crash.ui
那么这是为啥?spa
个人环境 Xcode:10.2.1 Mac:macOS Mojave version 10.14.4 iPhone: iOS 12.2 iPhone 8 Plus 模拟器线程
1. 使用 Timer 时,也可使用 Common,可是依然可使用。这里为啥不行?
2. Runloop 只能在一个特定的模式下运行,那么 Common 是否是由于包含了多种,因此不能正常使用?(可是 Common 包含了 Default)
复制代码
带着思考我去翻了源码.先看看 Timer 的流程.3d
CFRunLoopAddTimer(_rl, (CFRunLoopTimerRef)timer, (CFStringRef)mode);
rl->_commonModeItems
中,最终添加到新的 Commond 中CFSetApplyFunction(set, (__CFRunLoopAddItemToCommonModes), (void *)context);
复制代码
因此为何 time 使用 Common 却能够,由于是由于对 Common 对了转换,作了特殊处理。code
那么,在来结合源码看看orm
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate
复制代码
方法。cdn
他最终会走到 Foundation 中的 moreWork = CFRunLoopRunInMode((CFStringRef)mode, t, true) == kCFRunLoopRunHandledSource;
方法中。
当返回值是 kCFRunLoopRunHandledSource 时,返回一个 true,来完成这次运行。
随便在说一下这两个方法,他们为何不会退出。
接上,那么底层的 CoreFoundation 会对于传入不一样的 mode 作特殊处理吗? 带着问题我翻看源码。
SInt32 CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */
CHECK_FOR_FORK();
return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName, seconds, returnAfterSourceHandled);
}
复制代码
那么为何设置为 Common 会 crash 了?
我有找了不少资料。
在一片文章中找到了以下内容:
因此会挂的缘由是由于: Common是一个模式合集
,而非一个具体的模式,在这里须要的是一个具体的模式,因此就会 crash.
另外:
CFRunLoopRun(); // 启动
CFRunLoopStop(CFRunLoopGetCurrent()); // 中止
复制代码
这两个是能够启动和中止的.从源码来看
中止方法,最终会设置中止值。