1,NSThread
1.1初始化
NSThread *thread = [[NSThread alloc]initWithTarget:(id) selector:(SEL) object:(id)];
或者
[NSThread detachNewThreadSelector:(SEL) toTarget:(id) withObject:(id)];
selector:这个线程做什么任务(调哪个方法)
Target:谁来执行这个SEL方法
object:selector方法的传入参数,最多1个,可以传nil
注意:1、上面2个初始化方法的不同,init方法,需要通过 [线程名 start] ,线程才会开始执行。而detach方法,一旦初始化完成,自动执行。
2、selector方法的内部,需要用@autoreleasepool包起来,防止内存泄露
3、线程执行完,需要更新UI,一定要在主线程上更新
@autoreleasepool {
// xxxxxx;
// 在主线程上更新UI,SEL是更新UI的方法,id是SEL的参数,BOOL是YES表示执行完下面这句才会执行语句A
[需要更新UI的控件 performSelectorOnMainThread:@selector(SEL) withObject:(id) waitUntilDone:BOOL]; 语句A;
}
1.2NSThread的优缺点:
优点:简单
缺点:不能控制线程最大数量,不能控制线程的执行顺序
2.NSOperation之NSInvocation
NSOpeation的子类:NSInvocation、NSBlockOperation,只能使用子类。
类似CAAnimation,只能使用CAAnimation子类CABasicAnimation、CAKeyFrameAnimation、CATransition。
2.1初始化
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:(id) selector:(SEL) object:(id)];
selector:这个线程做什么任务(调哪个方法)
Target:谁来执行这个SEL方法
object:selector方法的传入参数,最多1个,可以传nil
2.2执行线程(在主线程上)
<span style="font-family: Arial, Helvetica, sans-serif;">[op start]; // 通过start方法,线程是直接在主队列运行</span>
2.3执行线程(在新线程上)
如果要开启新的线程,需要使用NSOperationQueue来管理线程,NSOperationQueue通常是属性
@property (strong, nonatomic) NSOperationQueue *queue;
[self.queue addOperation:op]; // op一旦添加到队列,就自动开启新线程
2.4设置线程的最大并发数量
[self.queue setMaxConcurrentOperationCount:4];
2.5设置多个线程之间的依赖关系
// 下载图片
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:(downloadImage) object:nil];
// 处理图片
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:(handleImage) object:nil];
// 显示图片
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:(showImage) object:nil];
// 设置依赖关系
[op2 addDependency:op1];
[op3 addDependency:op2];
// 添加线程到队列
[self.queue addOperation:op3];
[self.queue addOperation:op2];
[self.queue addOperation:op1];
3.NSOperation之NSBlockOperation
3.1初始化
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 这里添加该线程需要做的任务
}];
[self.queue addOperation:op];
3.3在NSInvocationOperation的基础上,补充更新UI界面,同样适用于NSInvocationOperation
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 在这里更新UI
}];
4.GCD
加载和更新UI都在一个方法里
// 1) 获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (UIImageView *imageView in self.imageViewSet) {
// 2) 在全局队列上异步调用方法,加载并更新图像
dispatch_async(queue, ^{
NSLog(@"GCD- %@", [NSThread currentThread]);
NSInteger num = arc4random_uniform(17) + 1;
NSString *imageName = [NSString stringWithFormat:@"NatGeo%02d.png", num];
// 通常此处的image是从网络上获取的
UIImage *image = [UIImage imageNamed:imageName];
// 3) 在在主线程队列中,调用异步方法设置UI
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"更新图片- %@", [NSThread currentThread]);
[imageView setImage:image];
});
});
}