转载

IOS开发-多线程编程技术(Thread、Cocoa operations、GCD)

前言:在软件开发中,多线程编程技术被广泛应用,相信多线程任务对我们来说已经不再陌生了。有了多线程技术,我们可以同做多个事情,而不是一个一个任务地进行。比如:前端和后台作交互、大任务(需要耗费一定的时间和资源)等等。也就是说,我们可以使用线程把占据时间长的任务放到后台中处理,而不影响到用户的使用。

线程的定义:

每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。

转自百度百科: 多线程

IOS支持的多线程技术:

一、Thread:

1)显式创建线程:NSThreed

2)隐式创建线程:NSObject

二、Cocoa operations:

NSOperation类是一个抽象类,因为我们必须使用它的两个子类。

1)NSInvocationOperation

2)NSBlockOperation

————————————————————————————

3)NSOperationQueue(继承于NSObject)

三、Grand Central Dispatch (GCD):

1)GCD的创建

2)重复执行线程:dispatch_apply

3)操作队列:dispatch_queue_create

4)GCD群组通知:dispatch_group_t

5)GCD实现计时器

一、Thread

我们可以使用NSTherad或NSObject类去调用:

1)显式创建线程:NSThread

创建NSThread有两个办法

1.1)创建之后需要使用start方法,才会执行方法:

NSThread *threadAlloc = [[NSThread alloc] initWithTarget:self selector:@selector(threadAlloc) object:nil]; [threadAlloc start];

1.2)创建并马上执行方法:

[NSThread detachNewThreadSelector:@selector(threadAlloc:) toTarget:self withObject:nil];

2)隐式创建线程:NSObject

我们也可以使用NSObject类的方法直接调用方法

[self performSelectorInBackground:@selector(threadAlloc) withObject:nil];

NSThread相关属性及方法:

// 获取/设置线程的名字 @property (copy) NSString *name NS_AVAILABLE(10_5, 2_0);  /**  *  获取当前线程的线程对象  *  *  通过这个属性可以查看当前线程是第几条线程,主线程为1。  *  可以看到当前线程的序号及名字,主线程的序号为1,依次叠加。  */ + (NSThread *)currentThread;  // 线程休眠(秒) + (void)sleepForTimeInterval:(NSTimeInterval)ti;  // 线程休眠,指定具体什么时间休眠 + (void)sleepUntilDate:(NSDate *)date;  // 退出线程  // 注意:这里会把线程对象销毁!销毁后就不能再次启动线程,否则程序会崩溃。 + (void)exit;

二、Cocoa operations

1)NSInvocationOperation

// 创建线程任务 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 线程A NSInvocationOperation *operation = [[NSInvocationOperation alloc]  initWithTarget:self  selector:@selector(operation1)  object:nil]; // 线程B NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]  initWithTarget:self  selector:@selector(operation2)  object:nil]; // 把线程A/B添加至队列 [queue addOperations:@[operation, operation2] waitUntilFinished:YES]; 

必须使用addOperations:方法把线程添加至队列,不然线程不会执行。或者,你也可以使用addOperation:方法添加单个线程。

2)NSBlockOperation

举个简单的使用列子介绍,都写了备注,就不再说明了:

// 创建线程任务 NSBlockOperation *blockOperation = [NSBlockOperation          blockOperationWithBlock:^{           NSLog(@"one - %@", [NSThread currentThread]);          }];; // 添加新的操作 [blockOperation addExecutionBlock:^{  NSLog(@"two - %@", [NSThread currentThread]); }]; // 添加新的操作 [blockOperation addExecutionBlock:^{  NSLog(@"three - %@", [NSThread currentThread]); }]; // 执行线程任务 [blockOperation start]; 

3)NSOperationQueue

这里介绍一下NSOperation的依赖关系,依赖关系会影响线程执行的顺序:

// 创建操作队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 线程A NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{  NSLog(@"op1");  [NSThread sleepForTimeInterval:2]; }]; // 线程B NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{  NSLog(@"op2"); }]; // 线程C NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{  NSLog(@"op3");  [NSThread sleepForTimeInterval:2]; }]; // 线程B依赖线程C,也就是等线程C执行完之后才会执行线程B [op2 addDependency:op3]; // 线程C依赖线程A,同上,只不过依赖对象改成了线程A [op3 addDependency:op1]; // 为队列添加线程 [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:op3]; 

注意:依赖关系可以多重依赖,但不要建立循环依赖。

在NSOperationQueue类中,我们可以使用cancelAllOperations方法取消所有的线程。这里需要说明一下,不是执行cancelAllOperations方法时就会马上取消,是等当前队列执行完,下面的队列不会再执行。

NSOperation方法及属性:

// 设置线程的最大并发数 @property NSInteger maxConcurrentOperationCount;  // 线程完成后调用的Block @property (copy) void (^completionBlock)(void);  // 取消线程 - (void)cancel;

只列举上面那些,其它的方法就不全列出来了。

三、Grand Central Dispatch (GCD)

1)GCD的创建:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{     NSLog(@"线程 - %@", [NSThread currentThread]); });

GCD也可以创建同步的线程,只需要把async改成sync即可。

2)重复执行线程:dispatch_apply

以下代码会执行4次:

dispatch_apply(4, DISPATCH_QUEUE_PRIORITY_DEFAULT, ^(size_t index) {     // index则为执行的次数 0开始递增     NSLog(@"one - %ld", index); });

index参数为执行的次数,0开始递增

3)操作队列:dispatch_queue_create

// 创建队列 // 第一个参数是“字符串标识”,第二个参数是可选的,可以是NULL dispatch_queue_t queue = dispatch_queue_create("com.garvey.post", NULL); // 传入一个队列并执行队列(顺序执行) dispatch_async(queue, ^{  NSLog(@"aaa");  [NSThread sleepForTimeInterval:2]; }); dispatch_async(queue, ^{  NSLog(@"bbb");  [NSThread sleepForTimeInterval:1]; }); dispatch_async(queue, ^{  NSLog(@"ccc"); }); 

代码效果:以上会先执行aaa-》bbb-》ccc

4)GCD群组通知:dispatch_group_t

GCD的高级用法,等所有线程都完成工作后,再作通知。

// 创建群组 dispatch_group_t group = dispatch_group_create(); // 线程A dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  NSLog(@"group1");  [NSThread sleepForTimeInterval:2]; }); // 线程B dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  NSLog(@"group2"); }); // 待群组里的线程都完成之后调用的通知 dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  NSLog(@"group success"); }); 

线程A和线程B都执行完之后,会调用通知打印group success。

5)GCD实现计时器

__block int time = 30; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0); dispatch_source_set_event_handler(timer, ^{  time--;  NSLog(@"%d", time);  if (time == 0) {   dispatch_source_cancel(timer);  } }); dispatch_resume(timer); 

代码效果:创建了一个计时器,计时器运行30秒,每过一秒会调用一次block,我们可以在block里面写代码。因为dispatch_source_t默认是挂起状态,因此我们使用时需要使用dispatch_resume方法先恢复,不然线程不会执行。

GCD方法及属性:

// 获取主线程 dispatch_get_main_queue()  // 创建队列:第一个参数是“字符串标识”,第二个参数是可选的,可以是NULL dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);  // 创建异步调度队列 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);  // 恢复队列 void dispatch_resume(dispatch_object_t object);  // 暂停队列 void dispatch_suspend(dispatch_object_t object);

本文参考:

iOS多线程开发

GCD的另一个用处是可以让程序在后台较长久的运行。

全面掌握iOS多线程攻略 —— PS:这个攻略较多,但是有很多重复的内容。

博文作者:GarveyCalvin

博文出处: http://www.cnblogs.com/GarveyCalvin/

本文版权归作者和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作!

正文到此结束
Loading...