iOS 中实现多线程的方法有很多,基于C的有pthread,GCD,基于OC的有NSThread,NSOperationQueue,后者是前者的封装,执行效率较差,推荐使用GCD,下面介绍下开启线程的方法。
pthread
// 创建线程
pthread_t myRestrict;
pthread_create(&myRestrict, NULL, run, NULL);
// 方法实现
void *run(void *data){
for (int i = 0; i<10000; i++){
NSLog(@"%d---%@", i, [NSThread currentThread]);
}
return NULL;
}
Thread
方法一
// 创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"http://b.png"];
thread.name = @"下载线程";
// 启动线程(调用self的download方法)
[thread start];
- (void)download:(NSString *)url{
NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
}
方法二
[NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"http://a.jpg"];
- (void)download:(NSString *)url{
NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
}
方法三
// 这2个不会创建线程,在当前线程中执行
// [self performSelector:@selector(download:) withObject:@"http://c.gif"];
// [self download:@"http://c.gif"];
// 这个方法会创建线程
[self performSelectorInBackground:@selector(download:) withObject:@"http://c.gif"];
- (void)download:(NSString *)url{
NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
}
GCD
async : 并发队列(最常用)
会不会创建线程:会,一般同时开多条
任务的执行方式:并发执行
// 获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 将任务添加全局队列中去异步执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
async : 串行队列(有时候用)
会不会创建线程:会,一般只开1条线程
任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
// 1.创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.test.queue", NULL);
// 2.将任务添加到串行队列中 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
// 3.非ARC,需要释放创建的队列
// dispatch_release(queue);
async -- 主队列(很常用)
// 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加任务到主队列中异步执行(结果还是串行)
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
sync -- 主队列(不能用---会卡死)
NSLog(@"syncMainQueue----begin--");
// 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加 任务 到主队列中 同步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
sync -- 并发队列
会不会创建线程:不会
任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
并发队列失去了并发的功能
// 获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 将 任务 添加到 全局并发队列 中 同步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
sync -- 串行队列
会不会创建线程:不会
任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
// 创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.text.queue", NULL);
// 将 任务 添加到 串行队列 中 同步 执行
dispatch_sync(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
NSOperationQueue
基本用法
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.添加操作到队列中(自动异步执行任务,并发)
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片1---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片2---%@", [NSThread currentThread]);
}];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperationWithBlock:^{
NSLog(@"下载图片3---%@", [NSThread currentThread]);}];
// 2个操作并发执行
最大并发数
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.设置最大并发(最多同时并发执行3个任务)
queue.maxConcurrentOperationCount = 3;
// 3.添加操作到队列中(自动异步执行任务,并发)
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片1---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片2---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片3---%@", [NSThread currentThread]);
}];
NSInvocationOperation *operation4 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[queue addOperation:operation4];
[queue addOperationWithBlock:^{
NSLog(@"下载图片5---%@", [NSThread currentThread]); }];
[queue addOperationWithBlock:^{
NSLog(@"下载图片6---%@", [NSThread currentThread]);
}];
//[queue cancelAllOperations];
设置依赖
/** 假设有A、B、C三个操作,
要求:1. 3个操作都异步执行
2. 操作C依赖于操作B
3. 操作B依赖于操作A
**/
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.创建3个操作
NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A1---%@", [NSThread currentThread]);
}];
// [operationA cancel];//取消单个
// [operationA addExecutionBlock:^{
// NSLog(@"A2---%@", [NSThread currentThread]);
// }];
// [operationA setCompletionBlock:^{
// NSLog(@"AAAAA---%@", [NSThread currentThread]);
// }];
NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"B---%@", [NSThread currentThread]);
}];
NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"C---%@", [NSThread currentThread]);
}];
// 设置依赖
[operationB addDependency:operationA];
[operationC addDependency:operationB];
// 3.添加操作到队列中(自动异步执行任务)
[queue addOperation:operationC];
[queue addOperation:operationA];
[queue addOperation:operationB];
异步回主线程
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// 1.异步下载图片
NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 2.回到主线程,显示图片(三种方法)//
[self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
// dispatch_async(dispatch_get_main_queue(), ^{
//
// });
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];
NSInvocationOperation
// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 创建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
// operation直接调用start,是同步执行(在当前线程执行操作)
// [operation start];
// 添加操作到队列中,会自动异步执行
[queue addOperation:operation];