iOS-GCD多线程编程详解2
iOS-GCD多线程编程详解2
一.前言
上一篇文章中简单的使用了GCD的多线程编程和有名的队列,今天将要讨论的是dispatch_apply函数的使用;
二.dispatch_apply说明
void dispatch_apply(size_t iterations, dispatch_queue_t queue,void (^block)(size_t));
该函数的主要作用是提交一个block到队列中多次执行,执行的次数由iterations决定,block中可以通过传递的参数知道是第几次执行索引,如果把它提交到一个并发队列中它就会并发执行,执行的顺序并不是按照索引决定的,所以在应用带函数对相同数据进行修改时要注意数据的完整性
参数:1.size_t iterations:block多次执行次数
2.queue:block提交的队列
3.void (^block)(size_t) :block实体
三.详细使用
1.把block提交到主队列
dispatch_apply(5, dispatch_get_main_queue(), ^(size_t i) { NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); });
运行结果是没有东西输出,屏幕卡死
2.把block交到global队列
<span style="white-space:pre"> </span>dispatch_apply(5, dispatch_get_global_queue(0, 0), ^(size_t i) { <span style="white-space:pre"> </span> NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); <span style="white-space:pre"> </span> });
运行结果:
第一次:
2015-01-05 23:12:07.367 GCDTest[716:38747] 我是第1次执行,我运行在线程<NSThread: 0x7fa2fa70d010>{number = 2, name = (null)}
2015-01-05 23:12:07.367 GCDTest[716:38703] 我是第0次执行,我运行在线程<NSThread: 0x7fa2fa40f930>{number = 1, name = main}
2015-01-05 23:12:07.367 GCDTest[716:38744] 我是第3次执行,我运行在线程<NSThread: 0x7fa2fa422940>{number = 3, name = (null)}
2015-01-05 23:12:07.367 GCDTest[716:38746] 我是第2次执行,我运行在线程<NSThread: 0x7fa2fa619cc0>{number = 4, name = (null)}
2015-01-05 23:12:07.368 GCDTest[716:38747] 我是第4次执行,我运行在线程<NSThread: 0x7fa2fa70d010>{number = 2, name = (null)}
第二次:
2015-01-05 23:13:04.578 GCDTest[726:39129] 我是第0次执行,我运行在线程<NSThread: 0x7fd3d25282c0>{number = 1, name = main}
2015-01-05 23:13:04.579 GCDTest[726:39129] 我是第4次执行,我运行在线程<NSThread: 0x7fd3d25282c0>{number = 1, name = main}
2015-01-05 23:13:04.578 GCDTest[726:39161] 我是第1次执行,我运行在线程<NSThread: 0x7fd3d24212e0>{number = 2, name = (null)}
2015-01-05 23:13:04.578 GCDTest[726:39163] 我是第2次执行,我运行在线程<NSThread: 0x7fd3d255f220>{number = 4, name = (null)}
2015-01-05 23:13:04.578 GCDTest[726:39164] 我是第3次执行,我运行在线程<NSThread: 0x7fd3d2537850>{number = 3, name = (null)}
第三次:
2015-01-05 23:13:50.186 GCDTest[731:39567] 我是第3次执行,我运行在线程<NSThread: 0x7fa113e14230>{number = 3, name = (null)}
2015-01-05 23:13:50.186 GCDTest[731:39567] 我是第4次执行,我运行在线程<NSThread: 0x7fa113e14230>{number = 3, name = (null)}
2015-01-05 23:13:50.186 GCDTest[731:39529] 我是第0次执行,我运行在线程<NSThread: 0x7fa113e135b0>{number = 1, name = main}
2015-01-05 23:13:50.186 GCDTest[731:39564] 我是第2次执行,我运行在线程<NSThread: 0x7fa113c10910>{number = 4, name = (null)}
2015-01-05 23:13:50.186 GCDTest[731:39566] 我是第1次执行,我运行在线程<NSThread: 0x7fa113f28390>{number = 2, name = (null)}
结果分析:三次运行中第一次运行的都在主线程,其余的都在非主线程,执行顺序是随机的,就可以猜想为什么在主队列会造成屏幕卡死,因为第一次调用是在主线程造成死锁。
3.把block提交到自定义系列队列中
<span style="white-space:pre"> </span>dispatch_queue_t customerQueue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL); <span style="white-space:pre"> </span> dispatch_apply(5, customerQueue, ^(size_t i) { <span style="white-space:pre"> </span> NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); <span style="white-space:pre"> </span> });
运行结果:在主线程中调用的结果
2015-01-05 23:21:34.973 GCDTest[760:41219] 我是第0次执行,我运行在线程<NSThread: 0x7fb3084283c0>{number = 1, name = main}
2015-01-05 23:21:34.974 GCDTest[760:41219] 我是第1次执行,我运行在线程<NSThread: 0x7fb3084283c0>{number = 1, name = main}
2015-01-05 23:21:34.974 GCDTest[760:41219] 我是第2次执行,我运行在线程<NSThread: 0x7fb3084283c0>{number = 1, name = main}
2015-01-05 23:21:34.974 GCDTest[760:41219] 我是第3次执行,我运行在线程<NSThread: 0x7fb3084283c0>{number = 1, name = main}
2015-01-05 23:21:34.974 GCDTest[760:41219] 我是第4次执行,我运行在线程<NSThread: 0x7fb3084283c0>{number = 1, name = main}
顺序执行并在主线程中执行,
运行结果:在子线程中的调用
-(void)netThread:(id)sender{ dispatch_queue_t customerQueue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL); dispatch_apply(5, customerQueue, ^(size_t i) { NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); }); }
2015-01-05 23:25:26.386 GCDTest[844:42550] 我是第0次执行,我运行在线程<NSThread: 0x7f9802684290>{number = 2, name = (null)}
2015-01-05 23:25:26.387 GCDTest[844:42550] 我是第1次执行,我运行在线程<NSThread: 0x7f9802684290>{number = 2, name = (null)}
2015-01-05 23:25:26.387 GCDTest[844:42550] 我是第2次执行,我运行在线程<NSThread: 0x7f9802684290>{number = 2, name = (null)}
2015-01-05 23:25:26.387 GCDTest[844:42550] 我是第3次执行,我运行在线程<NSThread: 0x7f9802684290>{number = 2, name = (null)}
2015-01-05 23:25:26.387 GCDTest[844:42550] 我是第4次执行,我运行在线程<NSThread: 0x7f9802684290>{number = 2, name = (null)}
顺序执行,也是在同一个线程中执行
4.把block提交到自定义的并发队列
dispatch_queue_t customerQueue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT); dispatch_apply(5, customerQueue, ^(size_t i) { NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); });
运行结果:在主线程中调用的结果
第一次:
2015-01-05 23:29:45.326 GCDTest[870:44074] 我是第1次执行,我运行在线程<NSThread: 0x7f9a0b724d00>{number = 2, name = (null)}
2015-01-05 23:29:45.326 GCDTest[870:44075] 我是第2次执行,我运行在线程<NSThread: 0x7f9a0b72b7a0>{number = 4, name = (null)}
2015-01-05 23:29:45.326 GCDTest[870:44077] 我是第3次执行,我运行在线程<NSThread: 0x7f9a0b5841c0>{number = 3, name = (null)}
2015-01-05 23:29:45.326 GCDTest[870:44034] 我是第0次执行,我运行在线程<NSThread: 0x7f9a0b528ac0>{number = 1, name = main}
2015-01-05 23:29:45.327 GCDTest[870:44074] 我是第4次执行,我运行在线程<NSThread: 0x7f9a0b724d00>{number = 2, name = (null)}
第二次:
2015-01-05 23:31:06.273 GCDTest[881:44838] 我是第0次执行,我运行在线程<NSThread: 0x7fdd78f13a70>{number = 1, name = main}
2015-01-05 23:31:06.274 GCDTest[881:44838] 我是第4次执行,我运行在线程<NSThread: 0x7fdd78f13a70>{number = 1, name = main}
2015-01-05 23:31:06.273 GCDTest[881:44903] 我是第3次执行,我运行在线程<NSThread: 0x7fdd78f99fc0>{number = 4, name = (null)}
2015-01-05 23:31:06.273 GCDTest[881:44901] 我是第1次执行,我运行在线程<NSThread: 0x7fdd78e218a0>{number = 2, name = (null)}
2015-01-05 23:31:06.273 GCDTest[881:44902] 我是第2次执行,我运行在线程<NSThread: 0x7fdd78d17640>{number = 3, name = (null)}
第三次:
2015-01-05 23:31:57.463 GCDTest[886:45383] 我是第2次执行,我运行在线程<NSThread: 0x7fa040d08370>{number = 4, name = (null)}
2015-01-05 23:31:57.463 GCDTest[886:45385] 我是第1次执行,我运行在线程<NSThread: 0x7fa040c2c510>{number = 3, name = (null)}
2015-01-05 23:31:57.463 GCDTest[886:45386] 我是第0次执行,我运行在线程<NSThread: 0x7fa040f16c20>{number = 2, name = (null)}
2015-01-05 23:31:57.463 GCDTest[886:45330] 我是第3次执行,我运行在线程<NSThread: 0x7fa040c291b0>{number = 1, name = main}
2015-01-05 23:31:57.464 GCDTest[886:45383] 我是第4次执行,我运行在线程<NSThread: 0x7fa040d08370>{number = 4, name = (null)}
说明block被提交的线程是随机的并没有规定那个线程执行
-(void)netThread:(id)sender{ dispatch_queue_t customerQueue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT); dispatch_apply(5, customerQueue, ^(size_t i) { NSLog(@"我是第%ld次执行,我运行在线程%@",i,[NSThread currentThread]); }); }
运行结果:在子线程中调用的结果
2015-01-05 23:33:22.767 GCDTest[910:46193] 我是第0次执行,我运行在线程<NSThread: 0x7f93e1e248c0>{number = 2, name = (null)}
2015-01-05 23:33:22.767 GCDTest[910:46188] 我是第3次执行,我运行在线程<NSThread: 0x7f93e1c1ce90>{number = 4, name = (null)}
2015-01-05 23:33:22.767 GCDTest[910:46190] 我是第1次执行,我运行在线程<NSThread: 0x7f93e1c1c010>{number = 3, name = (null)}
2015-01-05 23:33:22.768 GCDTest[910:46188] 我是第4次执行,我运行在线程<NSThread: 0x7f93e1c1ce90>{number = 4, name = (null)}
2015-01-05 23:33:22.767 GCDTest[910:46189] 我是第2次执行,我运行在线程<NSThread: 0x7f93e1e33fb0>{number = 5, name = (null)}
结果分析:多次结果都是随机的顺序,随机的线程
四.小结
dispatch_apply:要注意的问题是屏幕卡死的情况和对数据修改的完整性和正确性。