控制线程的生命周期
在主动结束线程前,使线程一直存在
- 初始化设置
- (instancetype)init {
self = [super init];
if (self) {
self.stoped = NO;
__weak typeof(self) weakSelf = self;
self.innerThread = [[AZThread alloc] initWithBlock:^{
//方式一: NSRunLoop
// [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
// while (weakSelf && !weakSelf.stoped) {
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
// }
//方式二: CFRunLoop
CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
//如果可以运行
while (weakSelf && !weakSelf.stoped) {
NSLog(@"RunLoop1");
@autoreleasepool {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, true);
}
NSLog(@"RunLoop2");
}
//某一时机,静态变量runAlways变为NO时,保证跳出RunLoop,线程推出
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
CFRelease(source);
NSLog(@"exist");
}];
}
return self;
}
- 开始
- (void)run{
if (!self.innerThread) return;
[self.innerThread start];
}
- 执行
- (void)excuteTask:(AZblock)block {
if (!self.innerThread || !block) return;
[self performSelector:@selector(task:) onThread:self.innerThread withObject:block waitUntilDone:NO];
}
- (void)task:(AZblock)block {
block();
}
- 结束
- (void)stop {
if (!self.innerThread) return;
[self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}
- (void)__stop {
self.stoped = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
self.innerThread = nil;
}
- (void)dealloc {
NSLog(@"%s", __func__);
[self stop];
}
线程中添加NSTimer
NSTimer在线程中将不影响主线程操作。
NSTimer的运行基于RunLoop,主线程[NSTimer scheduledTimerWithTimeInterval:target: selector: userInfo: repeats:]方法会自动加入runloop中。
主线程中处理复杂的UI界面时,NSTimer将被阻塞。
/**
添加runloop
*/
- (void)run:(id)__unused object {
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
// 添加timer
[self addTimerToRunLoop];
[runLoop run];
}
}
- (void)addTimerToRunLoop {
if (self.timer == nil) {
// scheduledTimerWithTimeInterval 这种方式
// 创建的 Timer 会默认加入到当前的 RunLoop 的 NSDefaultRunLoopMode 中
self.timer = [NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:@selector(runTimer)
userInfo:nil
repeats:YES];
}
}
- (void)runTimer {
NSLog(@"我是Timer,一直在run方法");
}
UITableView中的大图加载
//添加runloop监听者
- (void)addRunloopObserver {
// 获取 当前的Runloop ref - 指针
CFRunLoopRef current = CFRunLoopGetCurrent();
//上下文
CFRunLoopObserverContext context = {
0,
(__bridge void *)(self),
&CFRetain,
&CFRelease,
NULL
};
//定义一个RunloopObserver
CFRunLoopObserverRef defaultModeObserver;
// 创建观察者
defaultModeObserver = CFRunLoopObserverCreate(NULL,
kCFRunLoopBeforeWaiting, YES,
NSIntegerMax - 999,
&Callback,
&context);
//添加当前runloop的观察着
CFRunLoopAddObserver(current, defaultModeObserver, kCFRunLoopDefaultMode);
//释放
CFRelease(defaultModeObserver);
}
//这里处理耗时操作了
static void Callback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
//通过info桥接为当前的对象
PQRunloop * runloop = (__bridge PQRunloop *)info;
//如果没有任务,就直接返回
if (runloop.tasks.count == 0) {
return;
}
BOOL result = NO;
while (result == NO && runloop.tasks.count) {
//取出任务
RunloopBlock unit = runloop.tasks.firstObject;
//执行任务
result = unit();
//删除任务
[runloop.tasks removeObjectAtIndex:0];
}
}
//add task 添加任务
- (void)addTask:(RunloopBlock)unit withId:(id)key{
//添加任务到数组
[self.tasks addObject:unit];
[self.taskKeys addObject:key];
//为了保证加载到图片最大数是18所以要删除
if (self.tasks.count > self.maxQueue) {
[self.tasks removeObjectAtIndex:0];
[self.taskKeys removeObjectAtIndex:0];
}
}
监控应用卡顿
参考资料
www.jianshu.com/p/e9b4fafcb… www.jianshu.com/p/fa8bdff45… www.cnblogs.com/qiyiyifan/p…