ios-多线程-GCD
同步和异步
GCD
1.全局队列:
所有添加到全局队列中任务都是并发执行
定义全局队列:dispatch_queue_t queue = dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
可以往这个全局队列中塞各种任务,为执行这些队列,可能会开启多个线程,为什么可能呢?如果方法是同步,则不会开启新线程;如果方法是异步,会开启新线程,线程个数:随机(个人理解)
方法是谁?就是异步方法:dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>);同步方法:dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>);不废话,直接上代码!
- (IBAction)click2 { NSLog(@"click2---%@",[NSThread currentThread]); /* GCD 3种队列 全局队列:所有添加到全局队列中任务都是并发执行的(同时执行,可能会开启多个线程) dispatch_get_global_queue 串行队列:所有添加到串行队列中任务都是按顺序执行的(可能开一条线程)dispatch_queue_create 主队列:所有添加到主队列中任务都是在主线程中执行的 dispatch_get_main_queue() 同步还是异步,取决于方法名 dispatch_sync:同步:在当前线程执行任务,不会开启新的线程 dispatch_async:异步:在其他线程执行任务,会开启新的线程,开启多少条线程:随机 */ // 全局队列(同时执行,可能会开启多个线程:如果方法是同步,则不会开启新线程;如果方法是异步,会开启新线程,线程个数:随机) dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 异步执行队列(在其他线程执行任务,会开启新的线程,开启多少条线程:随机) dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); // 同步执行队列(在当前线程执行任务,不会开启新的线程,无论队列个数有多少个) dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); }
我们来看输出:
2015-04-22 17:47:42.240 多线程[869:29397] 主线程---<NSThread: 0x7fce69e0de80>{number = 1, name = main} 2015-04-22 17:47:43.102 多线程[869:29397] click2---<NSThread: 0x7fce69e0de80>{number = 1, name = main} 2015-04-22 17:47:43.102 多线程[869:29397] dispatch_sync queue---<NSThread: 0x7fce69e0de80>{number = 1, name = main} 2015-04-22 17:47:43.102 多线程[869:29397] dispatch_sync queue---<NSThread: 0x7fce69e0de80>{number = 1, name = main} 2015-04-22 17:47:43.102 多线程[869:29419] dispatch_async queue---<NSThread: 0x7fce69d324f0>{number = 2, name = (null)} 2015-04-22 17:47:43.102 多线程[869:29421] dispatch_async queue---<NSThread: 0x7fce69d314d0>{number = 3, name = (null)}
先看同步执行队列方法:dispatch_sync,我们看到这两个队列都采用同步方法执行,故系统不会为这两个队列开启新的线程,直接在主线程中执行。无论有多少个队列,只要都采用同步方法来执行,就是只在主线程中执行。
在看异步执行队列方法:dispatch_async,我们看到这两个队列都采用异步方法执行,故系统会分别为这两个队列各开启一个新的线程,来执行他们,可以看出这两个队列明显不是在一个线程中执行的。事实上,系统检测到有多个队列且采用异步方法执行时,会“随机”分配可用的线程给这些队列,即开启的新线程数并不完全等于异步方法个数,但绝对会开启新线程
上代码!
- (IBAction)click2 { NSLog(@"click2---%@",[NSThread currentThread]); /* GCD 3种队列 全局队列:所有添加到全局队列中任务都是并发执行的(同时执行,可能会开启多个线程) dispatch_get_global_queue 串行队列:所有添加到串行队列中任务都是按顺序执行的(可能开一条线程)dispatch_queue_create 主队列:所有添加到主队列中任务都是在主线程中执行的 dispatch_get_main_queue() 同步还是异步,取决于方法名 dispatch_sync:同步:在当前线程执行任务,不会开启新的线程 dispatch_async:异步:在其他线程执行任务,会开启新的线程,开启多少条线程:随机 */ // 全局队列(同时执行,可能会开启多个线程:如果方法是同步,则不会开启新线程;如果方法是异步,会开启新线程,线程个数:随机) dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 异步执行队列(在其他线程执行任务,会开启新的线程,开启多少条线程:随机)
dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ // 耗时操作 NSLog(@"dispatch_async queue---%@",[NSThread currentThread]); }); // 同步执行队列(在当前线程执行任务,不会开启新的线程,无论队列个数有多少个) dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ // 耗时操作 NSLog(@"dispatch_sync queue---%@",[NSThread currentThread]); }); }
上面有5个待执行的采用异步执行方法全局队列,5个待执行的采用同步执行方法的全局队列
输出结果:
2015-04-22 18:08:43.807 多线程[1073:37744] click2---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.808 多线程[1073:37744] dispatch_sync queue---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.808 多线程[1073:37948] dispatch_async queue---<NSThread: 0x7ff27240a780>{number = 4, name = (null)} 2015-04-22 18:08:43.808 多线程[1073:37744] dispatch_sync queue---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.809 多线程[1073:37744] dispatch_sync queue---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.809 多线程[1073:37744] dispatch_sync queue---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.809 多线程[1073:37744] dispatch_sync queue---<NSThread: 0x7ff272610300>{number = 1, name = main} 2015-04-22 18:08:43.809 多线程[1073:37948] dispatch_async queue---<NSThread: 0x7ff27240a780>{number = 4, name = (null)} 2015-04-22 18:08:43.810 多线程[1073:37948] dispatch_async queue---<NSThread: 0x7ff27240a780>{number = 4, name = (null)} 2015-04-22 18:08:43.808 多线程[1073:37949] dispatch_async queue---<NSThread: 0x7ff27251ade0>{number = 6, name = (null)} 2015-04-22 18:08:43.810 多线程[1073:37948] dispatch_async queue---<NSThread: 0x7ff27240a780>{number = 4, name = (null)}
我们看到采用同步执行方法(dispatch_sync)的全局队列都是在{number = 1, name = main}的主线程中执行的。
采用异步执行方法(dispatch_async)的全局队列都在非主线程中执行的,这说明系统为这些队列开启了新线程,但并没有开启5个新线程,因为线程开多了也会占用系统(cpu、内存等)资源,而是开启了两条新线程({number = 4, name = (null)}、{number = 6, name = (null)})来异步执行这5个队列。个人理解线程的利用也采用“循环利用”原则,为某个采用异步方法队列开启的某个线程一旦被该队列用完,如果还有新的异步队列需要被处理,接着就拿这个线程来用。
总结:
获得全局队列:dispatch_queue_t queue = dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
采用同步方法(dispatch_sync(<dispatch_queue_t queue>, <^(void)block>))来执行这些队列(队列里还有任务):不会开启新线程,在主线程里执行。界面的更新在主线程中执行。
采用异步方法来(dispatch_async(<dispatch_queue_t queue>, <^(void)block>))执行这些队列(队列里还有任务):会开启新线程,线程“循环利用”,线程数:随机。