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:要注意的问题是屏幕卡死的情况和对数据修改的完整性和正确性。





posted @ 2015-01-05 22:50  fineman  阅读(142)  评论(0编辑  收藏  举报