iOS多线程编程总结
2016-02-26 16:10
549 查看
摘录:/article/4834699.html
/article/1389856.html
1.、NSThread :这种方法需要管理线程的生命周期、同步、加锁问题,会导致一定的性能开销
2、Cocoa NSOperation :是基于OC实现的。NSOperation以面向对象的方式封装了需要执行的操作,然后可以将这个操作放到一个NSOperationQueue中去异步执行。不必关心线程管理、同步等问题。
3、GCD 全称:Grand Central Dispatch,简称GCD,iOS4才开始支持,是纯C语言的API。自iPad2开始,苹果设备开始有了双核CPU,为了充分利用这2个核,GCD提供了一些新特性来支持多核并行编程
参数说明:
selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象
argument:传输给target的唯一参数,也可以是nil
第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息
例子:
run:方法
已上面例子,对run:加锁
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等
2> 然后将NSOperation对象添加到NSOperationQueue中
3> 系统会自动将NSOperation中封装的操作放到一条新线程中执行
在此过程中,我们根本不用考虑线程的生命周期、同步、加锁等问题
1> NSInvocationOperation
2> NSBlockOperation
3> 自定义子类继承NSOperation,实现内部相应的方法
NSBlockOperation例子:
若要并发执行多个任务,可使用
自定义NSOperation:
如果NSInvocationOperation和NSBlockOperation不能满足需求,我们可以直接新建子类继承NSOperation,并添加任何需要执行的操作。如果只是简单地自定义NSOperation,只需要重载-(void)main这个方法,在这个方法里面添加需要执行的操作。
注意:如果创建NSOperation后直接使用
队列里可以加入很多个NSOperation, 可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。
通过下面的代码设置:
线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作。
一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
在 GCD 中有三种队列:主队列(main queue)、全局队列(global queue)、用户队列(user-created queue)。
*全局队列是并发队列,即队列中的任务(task)执行顺序和进入队列的顺序无关;
主队列是串行队列,队列中的任务按FIFO(first input first output,先进先出)的顺序执行。
用户队列是用户自己创建的队列,可创建串行的也可以创建并行的
*
队列创建
全局队列(global queue):
第一个参数用于指定优先级,分别使用DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW两个常量来获取高和低优先级的两个queue;第二个参数目前未使用到,默认0即可
主队列(main queue):
用户队列(user-created queue):
使用例子:
同步派发,执行时,会阻塞调用它的线程,然后执行block的内容,执行完成才能继续往下执行。
注意:不用在主线程中,将任务同步派发到主线程队列,会造成死锁。
b.异步派发dispatch_async
使用例子:
异步派发,执行时,不会阻塞调用它的线程,直接执行block内容。
c.其他
dispatch_group_async:可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。
例子:
dispatch_barrier_async:是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行。
其中,queue必须是用户通过
/article/1389856.html
简介
iOS有三种多线程编程的技术,分别是:1.、NSThread :这种方法需要管理线程的生命周期、同步、加锁问题,会导致一定的性能开销
2、Cocoa NSOperation :是基于OC实现的。NSOperation以面向对象的方式封装了需要执行的操作,然后可以将这个操作放到一个NSOperationQueue中去异步执行。不必关心线程管理、同步等问题。
3、GCD 全称:Grand Central Dispatch,简称GCD,iOS4才开始支持,是纯C语言的API。自iPad2开始,苹果设备开始有了双核CPU,为了充分利用这2个核,GCD提供了一些新特性来支持多核并行编程
1.NSThread
一个NSThread实例就代表着一条线程创建
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
参数说明:
selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象
argument:传输给target的唯一参数,也可以是nil
第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息
例子:
// 初始化线程 2 NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"userinfo"] autorelease]; 3 // 开启线程 4 [thread start];
run:方法
- (void)run:(NSString *)string { NSThread *current = [NSThread currentThread]; NSLog(@"执行了run:方法-参数:%@,当前线程:%@", string, current); } //结果 执行了run:方法-参数:userinfo,当前线程:<NSThread: 0x889e8d0>{name = (null), num = 3}
同步锁
创建锁可使用NSLock *theLock = [[NSLock alloc] init];
已上面例子,对run:加锁
- (void)run:(NSString *)string { [theLock lock]; NSThread *current = [NSThread currentThread]; NSLog(@"执行了run:方法-参数:%@,当前线程:%@", string, current); [theLock unlock]; }
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等
2、NSOperation
(1).思路:
1> 先将需要执行的操作封装到一个NSOperation对象中2> 然后将NSOperation对象添加到NSOperationQueue中
3> 系统会自动将NSOperation中封装的操作放到一条新线程中执行
在此过程中,我们根本不用考虑线程的生命周期、同步、加锁等问题
(2).创建
默认情况下,NSOperation并不具备封装操作的能力,必须使用它的子类,使用NSOperation子类的方式有3种:1> NSInvocationOperation
2> NSBlockOperation
3> 自定义子类继承NSOperation,实现内部相应的方法
(3).使用
NSInvocationOperation例子:NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@"userinfo"] autorelease]; NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [queue addOperation:operation];
NSBlockOperation例子:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){ NSLog(@"执行了一个新的操作"); }]; NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [queue addOperation:operation];
若要并发执行多个任务,可使用
NSBlockOperation的
addExecutionBlock:方法添加了新的操作
[operation addExecutionBlock:^() { NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]); }];
自定义NSOperation:
如果NSInvocationOperation和NSBlockOperation不能满足需求,我们可以直接新建子类继承NSOperation,并添加任何需要执行的操作。如果只是简单地自定义NSOperation,只需要重载-(void)main这个方法,在这个方法里面添加需要执行的操作。
注意:如果创建NSOperation后直接使用
[operation start];执行线程还是会在当前线程同步执行操作,并没有异步执行
(4).取消操作
operation开始执行之后, 默认会一直执行操作直到完成,我们也可以调用cancel方法中途取消操作[operation cancel];
(5).其他
如何控制线程池中的线程数?队列里可以加入很多个NSOperation, 可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。
通过下面的代码设置:
[queue setMaxConcurrentOperationCount:5];
线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作。
3.GCD
GCD的工作原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
(1).队列
GCD 是异步任务的技术之一,开发者可以用它将自定义的任务(task)追加到适当的派发队列(dispatch queue),就能生成必要的线程并执行任务。在 GCD 中有三种队列:主队列(main queue)、全局队列(global queue)、用户队列(user-created queue)。
*全局队列是并发队列,即队列中的任务(task)执行顺序和进入队列的顺序无关;
主队列是串行队列,队列中的任务按FIFO(first input first output,先进先出)的顺序执行。
用户队列是用户自己创建的队列,可创建串行的也可以创建并行的
*
队列创建
全局队列(global queue):
// 获取默认优先级的全局并发dispatch queue dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
第一个参数用于指定优先级,分别使用DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW两个常量来获取高和低优先级的两个queue;第二个参数目前未使用到,默认0即可
主队列(main queue):
dispatch_queue_t queue =dispatch_get_main_queue();//获取主线程队列
用户队列(user-created queue):
dispatch_queue_t serialQueue = dispatch_queue_create("cn.itcast.queue", NULL); //串行队列 dispatch_queue_t concurrentQueue = dispatch_queue_create("cn.itcast.queue", DISPATCH_QUEUE_CONCURRENT); //并行队列
(2).派发
a.同步派发dispatch_sync使用例子:
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 耗时的操作 });
同步派发,执行时,会阻塞调用它的线程,然后执行block的内容,执行完成才能继续往下执行。
注意:不用在主线程中,将任务同步派发到主线程队列,会造成死锁。
b.异步派发dispatch_async
使用例子:
dispatch_async(dispatch_get_main_queue(), ^{ // 更新界面 });
异步派发,执行时,不会阻塞调用它的线程,直接执行block内容。
c.其他
dispatch_group_async:可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。
例子:
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_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"group2"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"group3"); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"updateUi"); }); dispatch_release(group);
dispatch_barrier_async:是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行。
void dispatch_barrier_async( dispatch_queue_t queue, dispatch_block_t block);
其中,queue必须是用户通过
dispatch_queue_create创建的并行队列。如:
dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
(3)总结:
在使用GCD中,派发方式决定了改任务执行时,是否会阻塞调用线程。而执行的队列决定了该任务是串行执行还是并发执行。相关文章推荐
- iOS实战-自定义的横向滚动控件CustomScrollView
- Win8.1+Ubuntu双系统(BIOS+MBR)
- 深入浅出iOS函数式编程与响应式编程概念
- iOS推送之远程推送
- 深入理解IOS的RunLoop
- IOS学习 info.plist属性列表讲解(IOS)
- iOS 图标上的数字
- iOS实现侧拉栏抽屉效果
- iOS 学习资源
- iOS难理解的几个屏幕接触问题
- Nagios的安装配置与应用之四Nagios性能分析图表的实现
- ios学习笔记:控制器的切换
- iOS应用里面包含虚拟商品,支付必须使用苹果内购方式
- iOS 8 Auto Layout界面自动布局系列5-自身内容尺寸约束、修改约束、布局动画
- IOS 8 本地推送补充
- iOS代码性能优化
- iOS-内存管理
- iOS 插件卸载
- iOS支付宝开发遇到的问题
- iOS实现简单的抽屉效果