|
一、線程概述
1、
iOS里面的線程按種類可分為同步線程和異步線程。同步線程指調(diào)用同步線程的地方必須等到同步線程執(zhí)行完畢才可以繼續(xù)向下執(zhí)行。而調(diào)用異步線程的地方則在執(zhí)行完調(diào)用異步線程的語句后就可以繼續(xù)向下執(zhí)行。
2、
線程按調(diào)用方式又可以大致分為以下幾種類型:NSThread、NSOperation和GCD。NSThread
只能管理單個的線程,功能較簡單,GCD和NSOperation則可以進行隊列等復(fù)雜操作,且效率較高。其中GCD方式最為有
效,NSOperation是基于GCD封裝的,功能相對來說更豐富。
3、異步線程中往往要創(chuàng)建自己的自動釋放池來釋放異步線程中創(chuàng)建的自動釋放對象。
4、異步線程中有需要的話,要做自己的異常捕捉處理,因為當異步線程中產(chǎn)生異常時,主線程很有可能會捕捉不到異步線程拋出的異常。
一、NSThread
//
調(diào)用這種方法創(chuàng)建的線程會主動運行,不需要手動啟動
[NSThread
detachNewThreadSelector:@selector(downLoadImage:) toTarget:self
withObject:nil];
//
調(diào)用這種方式新建一個線程,新建完成后需要調(diào)用NSThread的start方法來啟動線程
NSThread
*thread = [[NSThread alloc] initWithTarget:self
selector:@selector(downLoadImage:) object:KURL];
[thread
start];
二、NSOperation
1.viewDidLoad方法里可以看到我們用NSInvocationOperation建了一個后臺線程,并且放到NSOperationQueue中。后臺線程執(zhí)行downloadImage方法。
2.downloadImage
方法處理下載圖片的邏輯。下載完成后用performSelectorOnMainThread執(zhí)行主線程updateUI方法。
3.updateUI 并把下載的圖片顯示到圖片控件中。
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(downLoadImage:)
object:KURL];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue
addOperation:operation];
1.隊列里可以加入很多個NSOperation,
可以把NSOperationQueue看作一個線程池,可往線程池中添加操作(NSOperation)到隊列中。線程池中的線程可看作消費者,從隊列中取走操作,并執(zhí)行它。
2.線程池中的線程數(shù),也就是并發(fā)操作數(shù)。默認情況下是-1,-1表示沒有限制,這樣會同時運行隊列中的全部的操作。
[queue
setMaxConcurrentOperationCount:5];
-
(void)downLoadImage:(NSString *)url
{
NSLog(@"url:%@", url);
NSURL *nsURL
= [NSURL URLWithString:url];
NSData *data
= [[NSData alloc] initWithContentsOfURL:nsURL];
UIImage
*image = [[UIImage alloc] initWithData:data];
[self
performSelectorOnMainThread:@selector(updateUI:) withObject:image
waitUntilDone:YES];
}
- (void)updateUI:(UIImage *)image
{
self.imageView.image = image;
}
二、GCD
dispatch_async
1.系統(tǒng)給每一個應(yīng)用程序提供了三個concurrent dispatch
queues。這三個并發(fā)調(diào)度隊列是全局的,它們只有優(yōu)先級的不同,因為是全局的,我們不需要去創(chuàng)建。我們只需要通過使用函數(shù)dispath_get_global_queue去得到隊列。
2.雖然dispatch queue是引用計數(shù)的對象,但是以上兩個都是全局的隊列,不用retain或release。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
NSURL *url = [NSURL URLWithString:KURL];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc] initWithData:data];
if (data != nil)
{
// 耗時操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
self.imageView.image = image;
});
}
});
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_queue_t queue2 =
dispatch_queue_create("gcdtest.rongfzh.yc",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_async-- 1");
});
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_async-- 2");
});
dispatch_barrier_async(queue2, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_barrier_async-- 1");
});
dispatch_barrier_async(queue2, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_barrier_async-- 2");
});
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_async3");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group3");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"updateUI");
[self updateUI];
});
|