小知识点关注iOS开发

iOS开发之多线程编程总结(二)

2016-11-04  本文已影响7371人  Dely

背景

担心了两周的我终于轮到去医院做胃镜检查了!去的时候我都想好了最坏的可能(胃癌),之前在网上查的症状都很相似。最后检查结果出来终于安心了,诊断结果:慢性非萎缩性胃炎(胃窦为主)

我是一个心里素质不过关的人,所以说对待问题的时候可能会有一种悲观的想法。朋友说我本来可能没病都被自己吓出病了,这是一个心态问题。

你们可能问我做胃镜什么感觉?我只能告诉你一个字:真爽,具体只能自己去感受。

自己眼中的自己.jpg

保持乐观的心态

看完下面的笑话就要开始我们的装逼之旅了_

  1. 一个大学生去公司实习,老板让他先从扫地开始。大学生:“我可是大学生哎……”老板:“哦,对了,我差点忘了你是大学生,来来来,我教你怎么扫地”
  1. 一天,老师让同学们写作文,题目是 《我的理想》。
    小明在作文里写道:我长大了要去抢银行,然后把钱分给穷苦老百姓。
    第二天老师改完了,写给小明的评语是这样的:很不错的理想,分钱的时候不要忘了老师,但你要注意你的同桌,他说他长大了要去当警察。

GCD基本介绍

GCD基本概念

这就需要上一篇博客里的基本知识了(不清楚去看下)iOS开发之多线程编程总结(一)

任务和队列

小结: 在以后的使用中,记住下面的就可以了!

  1. 开不开线程由执行任务的函数决定
  1. 开几条线程由队列决定

GCD的使用

今天我们学习下面图片的相关知识点,Demo下载链接会在文章最后给出来


GCD知识点.png

简单来看一段代码:异步下载图片

#pragma mark - 1.异步下载图片
- (IBAction)downLoadAction:(UIButton *)sender {
    self.imageView.image = nil;
    //获取全局队列
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //异步下载图片
        NSURL *url=[NSURL URLWithString:@"https://p1.bpimg.com/524586/475bc82ff016054ds.jpg"];
        //将资源转换为二进制
        NSData *data=[NSData dataWithContentsOfURL:url];
        //将二进制转化为图片
        UIImage *image=[UIImage imageWithData:data];
        
        //获取主队列,更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            //给图片控件赋值
            self.imageView.image=image;
        });
    });
}

NSThread对比可以发现

1. 串行队列(Serial Dispatch Queue)

串行队列的创建:
 dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
 dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
串行队列同步和异步执行Demo:
 #pragma mark - 串行队列同步和串行队列异步
 //串行队列同步
 - (void)serialQueueSyncMethod{
     //创建队列
     dispatch_queue_t queue = dispatch_queue_create("serialQueueSyncMethod", DISPATCH_QUEUE_SERIAL);
     //执行任务
     for (int i = 0; i < 6; i++) {
         NSLog(@"mainThread--->%d",i);
         dispatch_sync(queue, ^{
             NSLog(@"Current Thread=%@---->%d-----",[NSThread currentThread],i);
         });
     }
     NSLog(@"串行队列同步end");
  }

 //串行队列异步
  - (void)serialQueueAsyncMethod{
     dispatch_queue_t queue = dispatch_queue_create("serialQueueAsyncMethod", DISPATCH_QUEUE_SERIAL);
     for (int i = 0; i < 6; i++) {
         NSLog(@"mainThread--->%d",i);
         dispatch_async(queue, ^{
             NSLog(@"Current Thread=%@---->%d-----",[NSThread currentThread],i);
         });
     }
     NSLog(@"串行队列异步end");
  }   
串行队列 同步执行结果:
2016-11-03 17:16:35.794 ThreadDemo[27088:5268309] mainThread--->0
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->0-----
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] mainThread--->1
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->1-----
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] mainThread--->2
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->2-----
2016-11-03 17:16:35.795 ThreadDemo[27088:5268309] mainThread--->3
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->3-----
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] mainThread--->4
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->4-----
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] mainThread--->5
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] Current Thread=<NSThread: 0x60800007ae40>{number = 1, name = main}---->5-----
2016-11-03 17:16:35.796 ThreadDemo[27088:5268309] 串行队列同步end
串行队列 异步执行结果:
2016-11-03 17:22:25.074 ThreadDemo[27122:5273206] mainThread--->0
2016-11-03 17:22:25.074 ThreadDemo[27122:5273206] mainThread--->1
2016-11-03 17:22:25.074 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->0-----
2016-11-03 17:22:25.074 ThreadDemo[27122:5273206] mainThread--->2
2016-11-03 17:22:25.074 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->1-----
2016-11-03 17:22:25.074 ThreadDemo[27122:5273206] mainThread--->3
2016-11-03 17:22:25.075 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->2-----
2016-11-03 17:22:25.075 ThreadDemo[27122:5273206] mainThread--->4
2016-11-03 17:22:25.075 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->3-----
2016-11-03 17:22:25.075 ThreadDemo[27122:5273206] mainThread--->5
2016-11-03 17:22:25.075 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->4-----
2016-11-03 17:22:25.075 ThreadDemo[27122:5273206] 串行队列异步end
2016-11-03 17:22:25.075 ThreadDemo[27122:5273252] Current Thread=<NSThread: 0x60800007f380>{number = 5, name = (null)}---->5-----
小结:

2. 并发队列(Concurrent Dispatch Queue)

并发队列创建
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
并发队列同步和异步执行Demo
 #pragma mark - 并行队列同步和并行队列异步
 //并行队列同步
 - (void)concurrentQueueSyncMethod{
     dispatch_queue_t queue = dispatch_queue_create("concurrentQueueSyncMethod", DISPATCH_QUEUE_CONCURRENT);
    
     for (int i = 0; i < 6; i++) {
         dispatch_sync(queue, ^{
             NSLog(@"Current Thread=%@---->%d-----",[NSThread currentThread],i);
         });
     }
     NSLog(@"并行队列同步end");
  }

 //并行队列异步
- (void)concurrentQueueAsyncMethod{
     dispatch_queue_t queue = dispatch_queue_create("concurrentQueueAsyncMethod", DISPATCH_QUEUE_CONCURRENT);

     for (int i = 0; i < 6; i++) {
         dispatch_async(queue, ^{
             NSLog(@"Current Thread=%@---->%d-----",[NSThread currentThread],i);
         });
     }
    
     NSLog(@"并行队列异步end");
  }      
并发 队列同步执行结果:
2016-11-03 17:49:33.850 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->0-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->1-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->2-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->3-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->4-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] Current Thread=<NSThread: 0x60000007bf00>{number = 1, name = main}---->5-----
2016-11-03 17:49:33.851 ThreadDemo[27176:5290096] 并行队列同步end
并发队列 异步执行结果:
2016-11-03 18:33:32.794 ThreadDemo[27283:5311953] 并行队列异步end
2016-11-03 18:33:32.794 ThreadDemo[27283:5312009] Current Thread=<NSThread: 0x60800026b8c0>{number = 3, name = (null)}---->0-----
2016-11-03 18:33:32.794 ThreadDemo[27283:5312006] Current Thread=<NSThread: 0x600000269180>{number = 4, name = (null)}---->1-----
2016-11-03 18:33:32.794 ThreadDemo[27283:5312003] Current Thread=<NSThread: 0x600000268f80>{number = 6, name = (null)}---->3-----
2016-11-03 18:33:32.794 ThreadDemo[27283:5312174] Current Thread=<NSThread: 0x60800026b740>{number = 8, name = (null)}---->5-----
2016-11-03 18:33:32.794 ThreadDemo[27283:5312004] Current Thread=<NSThread: 0x60800026b7c0>{number = 5, name = (null)}---->2-----
2016-11-03 18:33:32.794 ThreadDemo[27283:5312173] Current Thread=<NSThread: 0x60800026b800>{number = 7, name = (null)}---->4-----
小结:

3. 全局队列(Global Dispatch Queue)

全局队列基本知识
  #define DISPATCH_QUEUE_PRIORITY_HIGH 2
  #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
  #define DISPATCH_QUEUE_PRIORITY_LOW (-2)
  #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
全局队列同步和异步执行Demo
 #pragma mark -全局队列同步和全局队列异步(工作表现与并发队列一致)
 //全局队列同步
 - (void)globalSyncMethod{
     //获取全局队列
       dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     //执行任务
     for (int i = 0; i < 10; ++i) {
         dispatch_sync(queue, ^{
             NSLog(@"global_queue_sync%@---->%d----",[NSThread currentThread],i);
         });
     }
     NSLog(@"global_queue_sync_end");
 }

 //全局队列异步
 - (void)globalAsyncMethod{
     //获取全局队列
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     //执行任务
     for (int i = 0; i < 10; ++i) {
         dispatch_async(queue, ^{
             NSLog(@"global_queue_async%@---->%d----",[NSThread currentThread],i);
         });
     }
     NSLog(@"global_queue_async_end");
 }
全局队列 同步执行结果:
2016-11-03 19:06:02.650 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->0----
2016-11-03 19:06:02.651 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->1----
2016-11-03 19:06:02.651 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->2----
2016-11-03 19:06:02.651 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->3----
2016-11-03 19:06:02.651 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->4----
2016-11-03 19:06:02.651 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->5----
2016-11-03 19:06:02.652 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->6----
2016-11-03 19:06:02.652 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->7----
2016-11-03 19:06:02.652 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->8----
2016-11-03 19:06:02.652 ThreadDemo[27347:5324064] global_queue_sync<NSThread: 0x600000072200>{number = 1, name = main}---->9----
2016-11-03 19:06:02.652 ThreadDemo[27347:5324064] global_queue_sync_end
全局队列 异步执行结果:
2016-11-03 19:12:00.242 ThreadDemo[27430:5333537] global_queue_async_end
2016-11-03 19:12:00.242 ThreadDemo[27430:5334057] global_queue_async<NSThread: 0x608000266100>{number = 5, name = (null)}---->0----
2016-11-03 19:12:00.242 ThreadDemo[27430:5334053] global_queue_async<NSThread: 0x600000263c80>{number = 6, name = (null)}---->1----
2016-11-03 19:12:00.242 ThreadDemo[27430:5334056] global_queue_async<NSThread: 0x600000263cc0>{number = 7, name = (null)}---->2----
2016-11-03 19:12:00.242 ThreadDemo[27430:5334063] global_queue_async<NSThread: 0x608000268500>{number = 8, name = (null)}---->3----
2016-11-03 19:12:00.242 ThreadDemo[27430:5334064] global_queue_async<NSThread: 0x600000263b80>{number = 9, name = (null)}---->4----
2016-11-03 19:12:00.243 ThreadDemo[27430:5334057] global_queue_async<NSThread: 0x608000266100>{number = 5, name = (null)}---->5----
2016-11-03 19:12:00.243 ThreadDemo[27430:5334053] global_queue_async<NSThread: 0x600000263c80>{number = 6, name = (null)}---->7----
2016-11-03 19:12:00.243 ThreadDemo[27430:5334065] global_queue_async<NSThread: 0x600000073600>{number = 10, name = (null)}---->6----
2016-11-03 19:12:00.243 ThreadDemo[27430:5334056] global_queue_async<NSThread: 0x600000263cc0>{number = 7, name = (null)}---->8----
2016-11-03 19:12:00.243 ThreadDemo[27430:5334066] global_queue_async<NSThread: 0x608000267d40>{number = 11, name = (null)}---->9----

4. 主队列(Main Dispatch Queue)

主队列基本知识
主队列同步和异步执行Demo
 #pragma mark -主队列同步和主队列异步
 //主队列同步
 - (void)mainSyncMethod{
     //获取主队列
     dispatch_queue_t queue = dispatch_get_main_queue();
     //执行任务
     for (int i = 0; i < 10; ++i) {
         dispatch_sync(queue, ^{
             NSLog(@"main_queue_sync%@---->%d----",[NSThread currentThread],i);
         });
     }
     NSLog(@"main_queue_sync_end");
 }

 //主队列异步
 - (void)mainAsyncMethod{
     //获取主队列
     dispatch_queue_t queue = dispatch_get_main_queue();
     //执行任务
     for (int i = 0; i < 10; ++i) {
         dispatch_async(queue, ^{
            NSLog(@"main_queue_async%@---->%d----",[NSThread currentThread],i);
         });
     }
     NSLog(@"main_queue_async_end");
 }
主队列 同步执行结果:
主线程和主队列相互等待造成死锁,程序会直接卡死!
原因:源代码在Main Dispatch Queue 即主队列中执行指定的block任务,并等待其结束。而其实在主线程中正在执行这些源代码,所以无法执行追加到Main Dispatch Queue 的block任务。
下面例子也一样:
dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        dispatch_sync(queue, ^{
            NSLog(@"main_queue_sync%@----",[NSThread currentThread]);
        });
    });

主队列 异步执行结果:
2016-11-03 19:45:38.154 ThreadDemo[27501:5349956] main_queue_async_end
2016-11-03 19:45:38.155 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->0----
2016-11-03 19:45:38.155 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->1----
2016-11-03 19:45:38.155 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->2----
2016-11-03 19:45:38.155 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->3----
2016-11-03 19:45:38.155 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->4----
2016-11-03 19:45:38.156 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->5----
2016-11-03 19:45:38.156 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->6----
2016-11-03 19:45:38.156 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->7----
2016-11-03 19:45:38.156 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->8----
2016-11-03 19:45:38.156 ThreadDemo[27501:5349956] main_queue_async<NSThread: 0x608000070880>{number = 1, name = main}---->9----

5.延迟执行(dispatch_after)

 dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
 delay(2){
 dispatch_async(queue, ^{
     dispatch_async(dispatch_get_main_queue(), ^{
     add task to mainQueue
    });
  });
 }
延迟执行(dispatch_after)Demo
#pragma mark -  延迟执行
 - (void)GCDAfterRunMethod{
     // 循环5次
     for (int i =0; i < 10000; i++ ) {
         NSLog(@"let's go %d",i);
         // 设置2秒后执行block
         dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
         dispatch_after(time, dispatch_get_main_queue(), ^{
             NSLog(@"This is my %d number!%@",i,[NSThread currentThread]);
         });
     }
       //等价于下面实现
 //    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
 //    for (int i = 0; i < 10000; i++) {  //        NSLog(@"let's go %d",i);
 //        dispatch_async(queue, ^{
 //           dispatch_async(dispatch_get_main_queue(), ^{  //                NSLog(@"This is my %d number!%@",i,[NSThread currentThread]);
 //           });
 //        });
 //    }
 }
注意:
  参数1获取指定的时间开始,通常为DISPATCH_TIME_NOW,定义:
  #define DISPATCH_TIME_NOW (0ull)//现在
  #define DISPATCH_TIME_FOREVER (~0ull)//永远,意味着你用它你的任务永远不会执行了!
参数2是从参数1延迟指定的时间来执行任务,也是一个时间
#define NSEC_PER_SEC 1000000000ull
#define NSEC_PER_MSEC 1000000ull
#define USEC_PER_SEC 1000000ull
#define NSEC_PER_USEC 1000ull
ull是C语言的数值字面量,是显示表明类型是使用的字符串(表示“unsigned long long”)
NSEC_PER_SEC 是秒的单位数量级 等价于1亿纳秒
上面代码中提到的(int64_t)(2 * NSEC_PER_SEC))就是2秒了

2.使用dispatch_walltime函数生成dispatch_time_t,用于计算绝对时间,例如在dispatch_after函数中指定2016年11月3日21时45分1秒这一绝对时间,可粗略的闹钟功能来使用。也就是到指定时间就会执行任务

//由NSDate类对象获取dispatch_time_t传递给dispatch_after函数使用
dispatch_time_t  getDispatchTimeByDate(NSDate *date){
NSTimeInterval interval;
double second,subSecond;
struct timespec time;
dispatch_time_t milestone;
   
interval = [date timeIntervalSince1970];
   
subSecond = modf(interval, &second);
time.tv_sec = second;
time.tv_nsec = subSecond * NSEC_PER_SEC;

milestone = dispatch_walltime(&time, 0);
return milestone;
}

6. 更改优先级(dispatch_set_target_queue)

1. dispatch_set_target_queue第一个Demo:

 - (void)GCDSetTargetQueueMethod{
    
     dispatch_queue_t targetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    
     dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
     dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
      //更改优先级
     dispatch_set_target_queue(queue1, targetQueue);
    
     for (int i = 0; i < 6; i++) {
         dispatch_async(queue1, ^{
         NSLog(@"queue1-currentThread = %@-->%d",[NSThread currentThread],i);
         });
     }
     for (int i = 0; i < 6; i++) {
          dispatch_async(queue2, ^{
          NSLog(@"queue2-----currentThread = %@----->%d",[NSThread currentThread],i);
          });
     }
 } 
打印结果:
2016-11-04 11:14:57.034 ThreadDemo[28477:5530919] queue2-----currentThread = <NSThread: 0x60000007e0c0>{number = 11, name = (null)}----->1
2016-11-04 11:14:57.034 ThreadDemo[28477:5530920] queue2-----currentThread = <NSThread: 0x60000007a140>{number = 12, name = (null)}----->2
2016-11-04 11:14:57.034 ThreadDemo[28477:5530918] queue2-----currentThread = <NSThread: 0x60000007a100>{number = 10, name = (null)}----->0
2016-11-04 11:14:57.034 ThreadDemo[28477:5530919] queue2-----currentThread = <NSThread: 0x60000007e0c0>{number = 11, name = (null)}----->3
2016-11-04 11:14:57.034 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->0
2016-11-04 11:14:57.034 ThreadDemo[28477:5530920] queue2-----currentThread = <NSThread: 0x60000007a140>{number = 12, name = (null)}----->5
2016-11-04 11:14:57.034 ThreadDemo[28477:5530921] queue2-----currentThread = <NSThread: 0x60000007c340>{number = 13, name = (null)}----->4
2016-11-04 11:14:57.035 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->1
2016-11-04 11:14:57.036 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->2
2016-11-04 11:14:57.036 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->3
2016-11-04 11:14:57.036 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->4
2016-11-04 11:14:57.037 ThreadDemo[28477:5530912] queue1-currentThread = <NSThread: 0x60000007ec00>{number = 9, name = (null)}-->5
打印解释:
在上面全局队列中说到了优先级的事情
因为XNU内核用于Global Dispatch Queue的线程并不能保证实时性,因此执行优先级知识大概的判断和区分,
所有我们不能完全依赖这个优先级来做队列的顺序事情,否则会出现问题!切记

2. dispatch_set_target_queue第一个Demo:

 - (void)GCDSetTargetQueueMethod{
     dispatch_queue_t targetQueue = dispatch_queue_create("targetQueue", DISPATCH_QUEUE_SERIAL);//目标队列
     dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);//串行队列
     dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);//并发队列
     //设置参考
     dispatch_set_target_queue(queue1, targetQueue);
     dispatch_set_target_queue(queue2, targetQueue);
    
     for (int i = 0; i < 6; i++) {
       dispatch_async(queue1, ^{
           NSLog(@"queue1-currentThread = %@-->%d",[NSThread currentThread],i);
       });
   }
   for (int i = 0; i < 6; i++) {
         dispatch_async(queue2, ^{
             NSLog(@"queue2-currentThread = %@-->%d",[NSThread currentThread],i);
         });
     }
    
 }
打印结果:
2016-11-04 11:34:34.722 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->0
2016-11-04 11:34:34.723 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->1
2016-11-04 11:34:34.723 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->2
2016-11-04 11:34:34.723 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->3
2016-11-04 11:34:34.723 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->4
2016-11-04 11:34:34.723 ThreadDemo[28551:5540844] queue1-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->5
2016-11-04 11:34:34.724 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->0
2016-11-04 11:34:34.724 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->1
2016-11-04 11:34:34.724 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->2
2016-11-04 11:34:34.724 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->3
2016-11-04 11:34:34.724 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->4
2016-11-04 11:34:34.725 ThreadDemo[28551:5540844] queue2-currentThread = <NSThread: 0x60000007b640>{number = 3, name = (null)}-->5
打印解释:

** dispatch_set_target_queue小结:**

7. 任务组Dispatch Group

1.队列与组自动关联并执行
 //自动执行任务组
 - (void)GCDAutoDispatchGroupMethod{
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     dispatch_group_t group = dispatch_group_create();
   
     for (int i = 0; i < 6; i++) {
           dispatch_group_async(group, queue, ^{
             NSLog(@"current Thread = %@----->%d",[NSThread currentThread],i);
         });
     }

     dispatch_group_notify(group, dispatch_get_main_queue(), ^{
         NSLog(@"current Thread = %@----->这是最后执行",[NSThread   currentThread]);
     });
}
打印结果:
2016-11-04 15:11:34.010 ThreadDemo[29225:5641180] current Thread = <NSThread: 0x600000468200>{number = 5, name = (null)}----->2
2016-11-04 15:11:34.010 ThreadDemo[29225:5641193] current Thread = <NSThread: 0x60800007f900>{number = 3, name = (null)}----->0
2016-11-04 15:11:34.011 ThreadDemo[29225:5641438] current Thread = <NSThread: 0x608000467980>{number = 8, name = (null)}----->5
2016-11-04 15:11:34.010 ThreadDemo[29225:5641178] current Thread = <NSThread: 0x608000467640>{number = 6, name = (null)}----->3
2016-11-04 15:11:34.010 ThreadDemo[29225:5641177] current Thread = <NSThread: 0x6080004675c0>{number = 4, name = (null)}----->1
2016-11-04 15:11:34.010 ThreadDemo[29225:5641437] current Thread = <NSThread: 0x600000467f40>{number = 7, name = (null)}----->4
2016-11-04 15:11:34.011 ThreadDemo[29225:5641137] current Thread = <NSThread: 0x60800007e200>{number = 1, name = main}----->这是最后执行
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, ^{NSLog(@"blk0");});
dispatch_group_async(group, queue, ^{NSLog(@"blk1");});
dispatch_group_async(group, queue, ^{NSLog(@"blk2");});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

   //等待group处理结束
//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
   dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1*USEC_PER_SEC));//1微秒
   long result = dispatch_group_wait(group, time);
   if (result == 0) {
       //属于Dispatch Group 的block任务全部处理结束
       NSLog(@"Dispatch Group全部处理完毕");

   }else{
       //属于Dispatch Group 的block任务还在处理中
       NSLog(@"Dispatch Group正在处理");
   }

long result = diaptach_group_wait(group, DISPACH_TIME_NOW);
2. 队列与组手动关联并执行
//手动执行任务组
 - (void)GCDManualDispatchGroupMethod{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    for (int i = 0; i < 6; i++) {
        
        dispatch_group_enter(group);//进入队列组
        
        dispatch_async(queue, ^{
            NSLog(@"current Thread = %@----->%d",[NSThread currentThread],i);
            
            dispatch_group_leave(group);//离开队列组
        });
    }
    
    long result = dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//阻塞当前线程,直到所有任务执行完毕才会继续往下执行
    if (result == 0) {
        //属于Dispatch Group 的block任务全部处理结束
        NSLog(@"Dispatch Group全部处理完毕");

    }else{
        //属于Dispatch Group 的block任务还在处理中
        NSLog(@"Dispatch Group正在处理");
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"current Thread = %@----->这是最后执行",[NSThread currentThread]);
    });
 }
打印结果:dispatch_group_wait()函数下方的print()函数在所有任务执行完毕之前是不会被调用的,因为dispatch_group_wait()会将当前线程进行阻塞。当然虽然是手动的将队列与任务组进行关联的,感觉display_group_notify()函数还是好用的。
2016-11-04 16:19:13.802 ThreadDemo[29402:5678525] current Thread = <NSThread: 0x600000271780>{number = 5, name = (null)}----->2
2016-11-04 16:19:13.802 ThreadDemo[29402:5678527] current Thread = <NSThread: 0x608000077300>{number = 3, name = (null)}----->0
2016-11-04 16:19:13.802 ThreadDemo[29402:5678524] current Thread = <NSThread: 0x60800007d840>{number = 4, name = (null)}----->1
2016-11-04 16:19:13.803 ThreadDemo[29402:5678760] current Thread = <NSThread: 0x600000271cc0>{number = 8, name = (null)}----->5
2016-11-04 16:19:13.802 ThreadDemo[29402:5678545] current Thread = <NSThread: 0x60800007d000>{number = 6, name = (null)}----->3
2016-11-04 16:19:13.802 ThreadDemo[29402:5678544] current Thread = <NSThread: 0x60800007d040>{number = 7, name = (null)}----->4
2016-11-04 16:19:13.803 ThreadDemo[29402:5678489] Dispatch Group全部处理完毕
2016-11-04 16:19:13.804 ThreadDemo[29402:5678489] current Thread = <NSThread: 0x600000069dc0>{number = 1, name = main}----->这是最后执行

8. 栅栏任务Dispatch_barrier_async

 #pragma mark - Dispatch_barrier_async
 - (void)GCDBarrierAsyncMethod{
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    void(^blk1_reading)(void) = ^{
         NSLog(@"blk1---reading");
    };
    
    void(^blk2_reading)(void) = ^{
        NSLog(@"blk2---reading");
    };
    void(^blk3_reading)(void) = ^{
        NSLog(@"blk3---reading");
    };
    void(^blk4_reading)(void) = ^{
        NSLog(@"blk4---reading");
    };
    void(^blk_writing)(void) = ^{
        NSLog(@"blk---writing");
    };
        
    dispatch_async(concurrentQueue, blk1_reading);
    dispatch_async(concurrentQueue, blk2_reading);
    
    //添加追加操作,,会等待b1和b2全部执行结束,执行完成追加操作b,才会继续并发执行下面操作
    dispatch_barrier_async(concurrentQueue, blk_writing);
    
    dispatch_async(concurrentQueue, blk3_reading);
    dispatch_async(concurrentQueue, blk4_reading);

}
打印结果:
2016-11-04 17:02:13.202 ThreadDemo[29492:5700974] blk2---reading
2016-11-04 17:02:13.202 ThreadDemo[29492:5700972] blk1---reading
2016-11-04 17:02:13.203 ThreadDemo[29492:5700972] blk---writing
2016-11-04 17:02:13.203 ThreadDemo[29492:5700972] blk3---reading
2016-11-04 17:02:13.203 ThreadDemo[29492:5700974] blk4---reading

9. 循环执行dispatch_apply

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     dispatch_apply(10, queue, ^(size_t index){
     NSLog(@"%zu", index);
});
    
NSLog(@"done");
2016-11-04 17:24:25.819 ThreadDemo[29598:5715955] 2
2016-11-04 17:24:25.819 ThreadDemo[29598:5715904] 0
2016-11-04 17:24:25.819 ThreadDemo[29598:5716588] 1
2016-11-04 17:24:25.819 ThreadDemo[29598:5716640] 3
2016-11-04 17:24:25.820 ThreadDemo[29598:5715955] 4
2016-11-04 17:24:25.820 ThreadDemo[29598:5715904] 5
2016-11-04 17:24:25.820 ThreadDemo[29598:5716588] 6
2016-11-04 17:24:25.820 ThreadDemo[29598:5716640] 7
2016-11-04 17:24:25.820 ThreadDemo[29598:5715904] 9
2016-11-04 17:24:25.820 ThreadDemo[29598:5715955] 8
2016-11-04 17:24:25.820 ThreadDemo[29598:5715904] done
#pragma mark - Dispatch_apply
 - (void)GCDDispatchApplyMethod{
   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    void(^blk1_reading)(void) = ^{
        NSLog(@"blk1---reading");
    };
    
    void(^blk2_reading)(void) = ^{
        NSLog(@"blk2---reading");
    };
    void(^blk3_reading)(void) = ^{
        NSLog(@"blk3---reading");
    };
    void(^blk_writing)(void) = ^{
        NSLog(@"blk---writing");
    };

    NSMutableArray *array = [NSMutableArray new];
    [array addObject:blk1_reading];
    [array addObject:blk2_reading];
    [array addObject:blk3_reading];
    [array addObject:blk_writing];
    
    dispatch_async(queue, ^{
        dispatch_apply(array.count, queue, ^(size_t index) {
            void (^blk)(void) = [array objectAtIndex:index];
            blk();
            NSLog(@"%zu====%@",index,[array objectAtIndex:index]);
        });
        NSLog(@"全部执行结束");
        dispatch_async(dispatch_get_main_queue(), ^{
            //在main Dispatch queue中执行处理,更新用户界面等待
            NSLog(@"done");
        });
    });

}
打印结果:
2016-11-04 17:36:02.258 ThreadDemo[29635:5723967] blk3---reading
2016-11-04 17:36:02.258 ThreadDemo[29635:5723940] blk2---reading
2016-11-04 17:36:02.258 ThreadDemo[29635:5723929] blk1---reading
2016-11-04 17:36:02.258 ThreadDemo[29635:5723968] blk---writing
2016-11-04 17:36:02.259 ThreadDemo[29635:5723940] 1====<__NSGlobalBlock__: 0x102895af0>
2016-11-04 17:36:02.259 ThreadDemo[29635:5723967] 2====<__NSGlobalBlock__: 0x102895b30>
2016-11-04 17:36:02.259 ThreadDemo[29635:5723929] 0====<__NSGlobalBlock__: 0x102895ab0>
2016-11-04 17:36:02.259 ThreadDemo[29635:5723968] 3====<__NSGlobalBlock__: 0x102895b70>
2016-11-04 17:36:02.259 ThreadDemo[29635:5723940] 全部执行结束
2016-11-04 17:36:02.259 ThreadDemo[29635:5723499] done

10. 队列的挂起和唤醒

#pragma mark -Dispatch_suspend/Dispatch_resume
- (void)GCDDispatch_suspend_resume{
    //系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断。
    
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", 0);
    dispatch_queue_t queue2 = dispatch_queue_create("queue2", 0);
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_async(queue1, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"%@-------%d",[NSThread currentThread],i);
            sleep(1);         
        }
    });
    
    dispatch_async(queue2, ^{
        NSLog(@"task2");
    });
    
    dispatch_group_async(group, queue1, ^{
        NSLog(@"task1 finished!");
    });
    dispatch_group_async(group, queue2, ^{
       dispatch_suspend(queue1);//挂起
       NSLog(@"task2 finished!挂起queue1");
       [NSThread sleepForTimeInterval:20.0];
       dispatch_resume(queue1);//唤醒队列
        
    });
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    dispatch_async(queue1, ^{
        NSLog(@"task3");
    });
    dispatch_async(queue2, ^{
        NSLog(@"task4");
    });
}
打印结果:可以先思考一下打印结果
2016-11-04 17:59:41.219 ThreadDemo[29749:5738141] task2
2016-11-04 17:59:41.219 ThreadDemo[29749:5738138] <NSThread: 0x60000027c380>{number = 4, name = (null)}-------0
2016-11-04 17:59:41.220 ThreadDemo[29749:5738141] task2 finished!挂起queue1
2016-11-04 17:59:42.220 ThreadDemo[29749:5738138] <NSThread: 0x60000027c380>{number = 4, name = (null)}-------1
2016-11-04 17:59:43.223 ThreadDemo[29749:5738138] <NSThread: 0x60000027c380>{number = 4, name = (null)}-------2
2016-11-04 17:59:44.225 ThreadDemo[29749:5738138] <NSThread: 0x60000027c380>{number = 4, name = (null)}-------3
2016-11-04 17:59:45.230 ThreadDemo[29749:5738138] <NSThread: 0x60000027c380>{number = 4, name = (null)}-------4
2016-11-04 18:00:01.220 ThreadDemo[29749:5738141] task1 finished!
2016-11-04 18:00:01.220 ThreadDemo[29749:5738141] task3
2016-11-04 18:00:01.221 ThreadDemo[29749:5738769] task4

11. 信号量Dispatch Semaphore

当并行执行的处理更新数据时,会产出数据不一致的情况,有时应用就会异常退出。可以使用Serial Dispatch Queue 和 dispatch_barrier也可以处理这种情况,我们也可以使用信号量Dispatch Semaphor来更好的处理线程安全和同步的问题。

Dispatch Semaphore是持有计数的信号。使用计数来实现该等待还是运行功能。计数为0时等待,计数为1或者大于1时,减去1而不是等待,就可以运行。

其实信号量就是根据pv操作来实现的

信号量就是一个资源计数器,对信号量有两个操作来达到互斥,分别是P和V操作。

一般情况是这样进行临界访问或互斥访问的: 设信号量值为1, 当一个进程1运行时,使用资源,进行P操作,即对信号量值减1,也就是资源数少了1个。这是信号量值为0。系统中规定当信号量值为0是,必须等待,直到信号量值不为零才能继续操作。 这时如果进程2想要运行,那么也必须进行P操作,但是此时信号量为0,所以无法减1,即不能P操作,也就阻塞。这样就到到了进程1排他访问。 当进程1运行结束后,释放资源,进行V操作。资源数重新加1,这是信号量的值变为1. 这时进程2发现资源数不为0,信号量能进行P操作了,立即执行P操作。信号量值又变为0.次数进程2咱有资源,排他访问资源。 这就是信号量来控制互斥的原理

信号量为0则阻塞线程,大于0则不会阻塞。则我们通过改变信号量的值,来控制是否阻塞线程,从而达到线程同步。

- (void)GCDDispatchSemaphore{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
  //创建一个信号量dispatch
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    NSMutableArray *array = [NSMutableArray new];
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            //一直等待信号量大于0
            dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, DISPATCH_TIME_FOREVER));
            
          //进行排他控制的处理代码...
          //将dispatch semphore的计数器减1 
            [array addObject:[NSNumber numberWithInteger:i]];
              
            //排他控制处理结束
            //将dispatch semphore的计数器加1    
            //如果有通过dispatch_semaphore_wait函数dispatch semphore的计数值增加的线程,等待就由最先等待的线程执行                  
            dispatch_semaphore_signal(semaphore);
        });
        
        NSLog(@"%@",array);
    }
}
long  result = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10*NSEC_PER_SEC)));
            
 if (result == 0){
      //进行排他控制的处理代码...
      //将dispatch semphore的计数器减1 
      [array addObject:[NSNumber numberWithInteger:i]];
              
      //排他控制处理结束
      //将dispatch semphore的计数器加1    
      //如果有通过dispatch_semaphore_wait函数dispatch semphore的计数值增加的线程,等待就由最先等待的线程执行                  
      dispatch_semaphore_signal(semaphore);
}else{
      //这个时候计数值为0,在达到指定时间为止还是等待状态。
        //处理逻辑....
}

GCD总结

  1. 开不开线程由执行任务的函数决定
  1. 开几条线程由队列决定
  1. GCD的使用步骤

结尾:

能看到这里的小伙伴都是真爱啊,内容太多了。学完这个你们多思考一下里面方法的联系以及实现,好了今天的GCD就讲到这里,中间有什么错误欢迎你们批评指出!下一篇博客将带你走进NSOperation。

喜欢的话就请点个喜欢加个关注_(楼主好无耻啊)❤️

ThreadDemo下载链接

参考书籍:Objective-C高级编程iOS与OS X多线程和内存管理

上一篇 下一篇

猜你喜欢

热点阅读