正常的线程任务完成后,线程就为finished状态,只能销毁再创建。如果想让一个线程常驻线程,实时的响应调度,则可以利用runloop高效的分配任务。
首先创建一个线程,代码很简单
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个线程
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByNormal) object:nil] ;
//
// self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFObserver) object:nil] ;
//
// self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFTimer) object:nil] ;
//
// self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunloopByCFSource) object:nil] ;
[self.thread start];
}
/**
* 一般创建runloop的方法。结果:成功
*/
- (void)createRunloopByNormal{
@autoreleasepool {
//添加port源,保证runloop正常轮询,不会创建后直接退出。
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
//开启runloop
[[NSRunLoop currentRunLoop] run];
}
}
上面的创建方式是工作中常用的方式,著名的AFNetworking就是用的这种方式开启的AFNetworking线程常驻。
下面测试一下线程是否退出
- (IBAction)btnClick:(id)sender {
NSLog(@"-----btnClick--------");
[self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}
- (void)test{
NSLog(@"----->Test");
}
能打印出 ----->Test 说明线程没有失效。
另外一种通过CoreFoundation创建runloop的方式
/**
* 通过向CFRunLoop 添加 Observer的方式,创建runloop。结果:失败
*/
- (void)createRunloopByCFObserver{
@autoreleasepool {
CFRunLoopRef runloop = CFRunLoopGetCurrent();
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"CFRunLoopActivity -->%zd",activity);
});
CFRunLoopAddObserver(runloop, observer, kCFRunLoopDefaultMode);
CFRelease(observer);
CFRunLoopRun();
}
}
/**
* 通过向CFRunLoop 添加 Timer的方式,创建runloop。结果:成功
*/
- (void)createRunloopByCFTimer{
@autoreleasepool {
CFRunLoopRef runloop = CFRunLoopGetCurrent();
CFRunLoopTimerRef timer = CFRunLoopTimerCreateWithHandler(CFAllocatorGetDefault(), CFAbsoluteTimeGetCurrent(), kCFAbsoluteTimeIntervalSince1904, 0, 0, ^(CFRunLoopTimerRef timer) {
});
CFRunLoopAddTimer(runloop, timer, kCFRunLoopDefaultMode);
CFRelease(timer);
CFRunLoopRun();
}
}
/**
* 通过向CFRunLoop 添加 Source的方式,创建runloop。结果:成功
*/
- (void)createRunloopByCFSource{
@autoreleasepool {
CFRunLoopRef runloop = CFRunLoopGetCurrent();
CFRunLoopSourceContext source_context;
bzero(&source_context, sizeof(source_context));
CFRunLoopSourceRef source = CFRunLoopSourceCreate(CFAllocatorGetDefault(), 0,&source_context );
CFRunLoopAddSource(runloop, source, kCFRunLoopDefaultMode);
CFRelease(source);
CFRunLoopRun();
}
}
通过测试,如果只是单纯的添加Observer,然后去启动runloop,runloop并不能长期的运行,会直接退出轮询。而另外的Source、Timer则能保证runloop正常运行。
小技巧:
1.Source、Timer、Observer可以组合使用
2. Observer能观察到runloop运行时的各种状态,能做很多事情
3. Timer创建会一直执行,需要在回调中将time失效。
网友评论