线程保活¶
子线程执行完任务之后就会自动销毁,频繁的创建和销毁线程会有资源浪费。使用runloop让线程长时间存活,而不被自动销毁。
线程和runloop是一对一的关系。
创建runloop:[NSRunLoop currentRunLoop]
runloop中如果没有source timer observer,[[NSRunLoop currentRunLoop] run];
会直接休眠。加入到当前的线程就没有用了,虽然存在,但是加入到当前子线程的任务不会执行。
三种方法:
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] addTimer:<#(nonnull NSTimer *)#> forMode:<#(nonnull NSRunLoopMode)#>];
CFRunLoopAddSource(<#CFRunLoopRef rl#>, <#CFRunLoopSourceRef source#>, <#CFRunLoopMode mode#>);
子线程需要加port事件源保活,主线程不需要source0 source1 timer observer保活。
// expects rl and rlm locked
static Boolean __CFRunLoopModeIsEmpty(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopModeRef previousMode) {
CHECK_FOR_FORK();
if (NULL == rlm) return true;
#if DEPLOYMENT_TARGET_WINDOWS
if (0 != rlm->_msgQMask) return false;
#endif
//主线程
Boolean libdispatchQSafe = pthread_main_np() && ((HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(__CFTSDKeyIsInGCDMainQ)));
if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) return false; // represents the libdispatch main queue
//子线程:三个判断
if (NULL != rlm->_sources0 && 0 < CFSetGetCount(rlm->_sources0)) return false;
if (NULL != rlm->_sources1 && 0 < CFSetGetCount(rlm->_sources1)) return false;
if (NULL != rlm->_timers && 0 < CFArrayGetCount(rlm->_timers)) return false;
struct _block_item *item = rl->_blocks_head;
while (item) {
struct _block_item *curr = item;
item = item->_next;
Boolean doit = false;
if (CFStringGetTypeID() == CFGetTypeID(curr->_mode)) {
doit = CFEqual(curr->_mode, rlm->_name) || (CFEqual(curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(rl->_commonModes, rlm->_name));
} else {
doit = CFSetContainsValue((CFSetRef)curr->_mode, rlm->_name) || (CFSetContainsValue((CFSetRef)curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(rl->_commonModes, rlm->_name));
}
if (doit) return false;
}
return true;
}
GCD和NSOperation都可以线程保活。
条件锁也可以进行线程保活。