一、线程概述
1、
iOS里面的线程按种类可分为同步线程和异步线程。同步线程指调用同步线程的地方必须等到同步线程执行完毕才可以继续向下执行。而调用异步线程的地方则在执行完调用异步线程的语句后就可以继续向下执行。
2、
线程按调用方式又可以大致分为以下几种类型:NSThread、NSOperation和GCD。NSThread
只能管理单个的线程,功能较简单,GCD和NSOperation则可以进行队列等复杂操作,且效率较高。其中GCD方式最为有
效,NSOperation是基于GCD封装的,功能相对来说更丰富。
3、异步线程中往往要创建自己的自动释放池来释放异步线程中创建的自动释放对象。
4、异步线程中有需要的话,要做自己的异常捕捉处理,因为当异步线程中产生异常时,主线程很有可能会捕捉不到异步线程抛出的异常。
一、NSThread
//
调用这种方法创建的线程会主动运行,不需要手动启动
[NSThread
detachNewThreadSelector:@selector(downLoadImage:) toTarget:self
withObject:nil];
//
调用这种方式新建一个线程,新建完成后需要调用NSThread的start方法来启动线程
NSThread
*thread = [[NSThread alloc] initWithTarget:self
selector:@selector(downLoadImage:) object:KURL];
[thread
start];
二、NSOperation
1.viewDidLoad方法里可以看到我们用NSInvocationOperation建了一个后台线程,并且放到NSOperationQueue中。后台线程执行downloadImage方法。
2.downloadImage
方法处理下载图片的逻辑。下载完成后用performSelectorOnMainThread执行主线程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)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。
2.线程池中的线程数,也就是并发操作数。默认情况下是-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.系统给每一个应用程序提供了三个concurrent dispatch
queues。这三个并发调度队列是全局的,它们只有优先级的不同,因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列。
2.虽然dispatch queue是引用计数的对象,但是以上两个都是全局的队列,不用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];
});
|