【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
后台线程
简单操作,无需创建线程时,可以使用一下函数(以UILabel 为例):
[myLabel performSelector:@selector(setText:) withObject:@"hello" afterDelay:0.1f];
代替平时的操作:[myLabel setText:@"hello"];
1)创建线程:执行线程函数,将函数要执行的任务从主界面线程中分离出来
[NSThread detachNewThreadSelector:@selector(listenForRequests) toTarget:self withObject:nil ];
-(void)listenForRequests
{
@autoreleasepool
{
//doSomething
........
}
}
注意:线程函数内创建的任何对象在函数执行完成以后不会得到协防,为防止内存泄漏,在线程函数中需使用@autoreleasepool{}进行内存管理。
RunLoop
说到 NSThread 就不能不说起与之关系相当紧密的 NSRunLoop。Run loop 相当于 win32 里面的消息循环机制,它可以让你根据事件/消息(鼠标消息,键盘消息,计时器消息等)来调度线程是忙碌还是闲置。
系统会自动为应用程序的主线程生成一个与之对应的 run loop 来处理其消息循环。在触摸 UIView 时之所以能够激发 touchesBegan/touchesMoved 等等函数被调用,就是因为应用程序的主线程在 UIApplicationMain 里面有这样一个 run loop 在分发 input 或 timer 事件。2) 使用通知中心通知主线程更新界面:在线程函数中发送消息,在主线程中注册监听消息
-(void)listenForRequests
{
@autoreleasepool
{
//doSomething
........
[[NSNotificationCenter defaultCenter] postNotificationName:@"updateUI" object: obj];
}
}
主线程注册监听:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePost:) name:@"updateUI" object:nil];
-(void)handlePost:(NSNotification *)notify
{
id obj = [notify object];
[self performSelectorOnMainThread:@selector(update:) withObject:obj waitUntilDone:YES];
}
注: 这里接收到消息后,有必要的话,可以再开启线程来处理相关操作。
附: 虽然传统的 NSThread 也可以进行多线程的管理,但是需要处理线程的声明周期,还要考虑线程同步、加锁等问题,会操作一定程度上的性能开销。
并发执行后台类 NSOperationQueue,分为4步来操作
1)定义一个操作类
a. 先定义一个回调接口,在任务完成后发送通知
@protocal LongTaskOperationProtocal<NSObject>
-(void) longTaskOperationFinished:(LongTaskOperation *)op;//接收 operation --LongTaskOperation 进行相关操作
b. 定义一个操作类
方法1. NSOperation子类 NAInvocationOperation
NAInvocationOperation *operation = [[NSInvocationOperation alloc]initWitTarget:self selector:@selector(listenForRequets) object:obj];
// 与当前线程同步执行代码 [operation star];
// 异步执行需加入到 NSOperationQueue 中
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
[operationQueue addOperation:operation];
方法2. NSOperation子类 NABlockOperation
// 并发执行一个线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"执行线程。");
}];
[blockOperation start];
// 并发执行多个线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"执行线程:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"执行一个并发线程线程:%@",[NSThread currentThread]);
}];
[blockOperation start];//并发的执行多个操作,分别在不同的线程中操作
注: 线程完成后执行操作 : operation.completionBlock = ^(){};
方法3. 自定义一个NSOperation的子类
#import "LongTaskOperationProtocal.h"
@interface LongTaskOperation:NSOperation
{
NSString *imgFilePath;
}
@property (nonatomic,assign) id<LongTaskOperationProtocal> delegate;
-(id)initWithPath:(NSString *)aPath;
2)编写操作类的main()函数
// LongTaskOperation.m
-(id)initWithPath:(NSString *)aPath
{
if (self == [super init]) {
}
return self;
}
//重写 NSOperation 的mian方法
-(void)main
{
if (!self.isCancelled) {
@autoreleasepool {
//do you back-end task
if (!self.isCancelled &&self.delegate) {
[self.delegate longTaskOperationFinished:self];
}
}
}
}
注意:mian函数中一定要 使用独立的 autoreleasepool 来管理操作类中的变量,否则会造成内存泄漏。
3)在需要进行耗时操作的类中创建操作类对象,并加入NSOperationQueue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue setMaxConcurrentOperationCount:[[NSProcessInfo processInfo] activeProcessorCount] + 1];//设置线程队列中的最多线程数
LongTaskOperation *operation = [[LongTaskOperation alloc]initWithPath:@"string"];
operation.delegate = self;
[queue addOperation:operation];
operation = nil;
//注意:操作加入队列后,要立即释放操作对象。
4)在进行耗时操作的类中定义操作完成函数
-(void) longTaskOperationFinished:(LongTaskOperation *)op
{........}
附:程序不需要队列时,释放队列
[ queue cancelAllOperations];
queue = nil;
来源:oschina
链接:https://my.oschina.net/u/818427/blog/201335