iOS 中實(shí)現(xiàn)多線程的方法有很多,基于C的有pthread,GCD,基于OC的有NSThread,NSOperationQueue,后者是前者的封裝,執(zhí)行效率較差,推薦使用GCD,下面介紹下開啟線程的方法。
pthread
// 創(chuàng)建線程
pthread_t myRestrict;
pthread_create(&myRestrict, NULL, run, NULL);
// 方法實(shí)現(xiàn)
void *run(void *data){
for (int i = 0; i<10000; i++){
NSLog(@"%d---%@", i, [NSThread currentThread]);
}
return NULL;
}
Thread
方法一
// 創(chuàng)建線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"http://b.png"];
thread.name = @"下載線程";
// 啟動(dòng)線程(調(diào)用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個(gè)不會(huì)創(chuàng)建線程,在當(dāng)前線程中執(zhí)行
// [self performSelector:@selector(download:) withObject:@"http://c.gif"];
// [self download:@"http://c.gif"];
// 這個(gè)方法會(huì)創(chuàng)建線程
[self performSelectorInBackground:@selector(download:) withObject:@"http://c.gif"];
- (void)download:(NSString *)url{
NSLog(@"下載---%@---%@", url, [NSThread currentThread]);
}
GCD
async : 并發(fā)隊(duì)列(最常用)
會(huì)不會(huì)創(chuàng)建線程:會(huì),一般同時(shí)開多條
任務(wù)的執(zhí)行方式:并發(fā)執(zhí)行
// 獲得全局的并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 將任務(wù)添加全局隊(duì)列中去異步執(zhí)行
dispatch_async(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
async : 串行隊(duì)列(有時(shí)候用)
會(huì)不會(huì)創(chuàng)建線程:會(huì),一般只開1條線程
任務(wù)的執(zhí)行方式:串行執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后再執(zhí)行下一個(gè)任務(wù))
// 1.創(chuàng)建一個(gè)串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("cn.test.queue", NULL);
// 2.將任務(wù)添加到串行隊(duì)列中 異步 執(zhí)行
dispatch_async(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
// 3.非ARC,需要釋放創(chuàng)建的隊(duì)列
// dispatch_release(queue);
async -- 主隊(duì)列(很常用)
// 1.主隊(duì)列(添加到主隊(duì)列中的任務(wù),都會(huì)自動(dòng)放到主線程中去執(zhí)行)
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加任務(wù)到主隊(duì)列中異步執(zhí)行(結(jié)果還是串行)
dispatch_async(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
sync -- 主隊(duì)列(不能用---會(huì)卡死)
NSLog(@"syncMainQueue----begin--");
// 1.主隊(duì)列(添加到主隊(duì)列中的任務(wù),都會(huì)自動(dòng)放到主線程中去執(zhí)行)
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加 任務(wù) 到主隊(duì)列中 同步 執(zhí)行
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
sync -- 并發(fā)隊(duì)列
會(huì)不會(huì)創(chuàng)建線程:不會(huì)
任務(wù)的執(zhí)行方式:串行執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后再執(zhí)行下一個(gè)任務(wù))
并發(fā)隊(duì)列失去了并發(fā)的功能
// 獲得全局的并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 將 任務(wù) 添加到 全局并發(fā)隊(duì)列 中 同步 執(zhí)行
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
sync -- 串行隊(duì)列
會(huì)不會(huì)創(chuàng)建線程:不會(huì)
任務(wù)的執(zhí)行方式:串行執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后再執(zhí)行下一個(gè)任務(wù))
// 創(chuàng)建一個(gè)串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("cn.text.queue", NULL);
// 將 任務(wù) 添加到 串行隊(duì)列 中 同步 執(zhí)行
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
NSOperationQueue
基本用法
// 1.創(chuàng)建一個(gè)隊(duì)列(非主隊(duì)列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.添加操作到隊(duì)列中(自動(dòng)異步執(zhí)行任務(wù),并發(fā))
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個(gè)操作并發(fā)執(zhí)行
最大并發(fā)數(shù)
// 1.創(chuàng)建一個(gè)隊(duì)列(非主隊(duì)列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.設(shè)置最大并發(fā)(最多同時(shí)并發(fā)執(zhí)行3個(gè)任務(wù))
queue.maxConcurrentOperationCount = 3;
// 3.添加操作到隊(duì)列中(自動(dòng)異步執(zhí)行任務(wù),并發(fā))
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];
設(shè)置依賴
/** 假設(shè)有A、B、C三個(gè)操作,
要求:1. 3個(gè)操作都異步執(zhí)行
2. 操作C依賴于操作B
3. 操作B依賴于操作A
**/
// 1.創(chuàng)建一個(gè)隊(duì)列(非主隊(duì)列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.創(chuàng)建3個(gè)操作
NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A1---%@", [NSThread currentThread]);
}];
// [operationA cancel];//取消單個(gè)
// [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]);
}];
// 設(shè)置依賴
[operationB addDependency:operationA];
[operationC addDependency:operationB];
// 3.添加操作到隊(duì)列中(自動(dòng)異步執(zhí)行任務(wù))
[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
// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 創(chuàng)建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
// operation直接調(diào)用start,是同步執(zhí)行(在當(dāng)前線程執(zhí)行操作)
// [operation start];
// 添加操作到隊(duì)列中,會(huì)自動(dòng)異步執(zhí)行
[queue addOperation:operation];