iOS 网络和线程模块源码分析征服iOS

深入浅出GCD —— 所学即所用

2017-01-10  本文已影响240人  EmptyWalker

CGD简介

什么是GCD

GCD的优势

GCD中的概念和使用步骤

2个核心概念

任务:

执行的什么操作,用block代码块的形式创建

队列:

是用来陈放任务的载体,负责调度任务;队列有两种类型:

使用步骤(2步)

定制任务

确定想要执行的任务

将任务添加到队列中

在这个过程中,我们需要做的就是:将任务以指定的方式(同步/异步)添加到队列中,队列就会按照我们指定的方式调度任务。

我的理解

队列、任务、线程池

如上图,GCD主要由任务、队列、执行方式三个部分组成,又由于队列类型(串行/并行)、执行方式(同步/异步)的不同,可以两两组合,从而出现四种情况,后面会一一通过代码来实现。这里主要说明的是:

下面,通过代码,来依次验证这些情况。

GCD实战

创建队列

所有的队列都是dispatch_queue_t类型,常用创建队列通常有三种方法,其中有两种是系统提供的:

     QOS_CLASS_USER_INTERACTIVE    用户交互(希望线程快速被执行,不要用好使的操作)
     QOS_CLASS_USER_INITIATED      用户需要的(同样不要使用耗时操作)
     QOS_CLASS_DEFAULT             默认的(给系统来重置队列的)
     QOS_CLASS_UTILITY             使用工具(用来做耗时操作)
     QOS_CLASS_BACKGROUND          后台
     QOS_CLASS_UNSPECIFIED         没有指定优先级

而在iOS 8之前版本表示的含义是:调度的优先级,其类型如下:

     DISPATCH_QUEUE_PRIORITY_HIGH 2               高优先级
     DISPATCH_QUEUE_PRIORITY_DEFAULT 0            默认优先级
     DISPATCH_QUEUE_PRIORITY_LOW (-2)             低优先级
     DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台优先级

提示

不要选择BACKGROUND 优先级,服务质量,因为线程执行会慢到令人发指!!!体现在任务调度次数少,执行时间短。通常基本都使用默认的,填入0

添加任务

添加任务:将任务以指定的执行方式添加到队列中去;它的方式有两种:

    /**
    *queue: 添加到的队列
    *block:就放我们需要执行的任务
    */
    dispatch_sync(dispatch_queue_t  _Nonnull queue, ^{
        //you todo 
    });
    dispatch_async(dispatch_queue_t  _Nonnull queue, ^{
    
        //you todo
    }) 

介绍完了基本函数语法,下面来用代码实现上述所说的4中情况。

串行队列同步执行

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    [self gcdBase1];
    
}

- (void)gcdBase1 {

    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_SERIAL);
    for (NSInteger i = 0; i < 10; i ++) {
        dispatch_sync(queue, ^{
            NSLog(@"%ld ------ %@", (long)i,  [NSThread currentThread]);
        });
    }
}

我在touchesBegan方法中,串行队列中以同步执行的方法添加了10个NSLog任务,当点击屏幕时,控制台获得以下输出:


2017-01-10 21:54:58.609 GCD-01[13124:1295897] 0 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.609 GCD-01[13124:1295897] 1 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.609 GCD-01[13124:1295897] 2 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.610 GCD-01[13124:1295897] 3 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.610 GCD-01[13124:1295897] 4 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.610 GCD-01[13124:1295897] 5 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.610 GCD-01[13124:1295897] 6 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.611 GCD-01[13124:1295897] 7 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.611 GCD-01[13124:1295897] 8 ------ <NSThread: 0x600000079e00>{number = 1, name = main}
2017-01-10 21:54:58.611 GCD-01[13124:1295897] 9 ------ <NSThread: 0x600000079e00>{number = 1, name = main}

由结果可以看出,不会开启线程,并且任务是顺序执行的,符合预期,并且无论你点击多少次,结果都不会改变。

串行队列异步执行

这次我在touchesBegan方法中执行以下任务,在一个串行队列中,添加10个异步任务,并且在任务添加后,打印一句I am here,猜猜这次的打印结果会是怎么样的?????

- (void)gcdBase2 {
    
    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_SERIAL);
    for (NSInteger i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"%ld ------ %@", (long)i,  [NSThread currentThread]);
        });
    }
    NSLog(@"I am here");
}

在模拟器中点击屏幕,获得以下结果:

2017-01-10 22:06:01.703 GCD-01[13385:1322583] I am here <NSThread: 0x600000066a40>{number = 1, name = main}
2017-01-10 22:06:01.703 GCD-01[13385:1322734] 0 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.703 GCD-01[13385:1322734] 1 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.703 GCD-01[13385:1322734] 2 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.703 GCD-01[13385:1322734] 3 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.704 GCD-01[13385:1322734] 4 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.704 GCD-01[13385:1322734] 5 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.704 GCD-01[13385:1322734] 6 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.705 GCD-01[13385:1322734] 7 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.705 GCD-01[13385:1322734] 8 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}
2017-01-10 22:06:01.705 GCD-01[13385:1322734] 9 ------ <NSThread: 0x61800006b0c0>{number = 3, name = (null)}

由以上结果可以看出,异步执行,会创建新的线程去执行任务,在串行队列中,由于每次只能拿一个任务,所以任务是按照FIFO顺序执行的。这里的I am here位置不一定一直处于第一位,但是肯定是靠前的。但是我试了很多次,都是第一位,尴尬。。。

并行队列同步执行

我在touchesBegan方法中执行以下任务;将队列类型换成DISPATCH_QUEUE_CONCURRENT,即并行队列,然后添加同步任务

- (void)gcdBase3 {
    
    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_CONCURRENT);
    for (NSInteger i = 0; i < 10; i ++) {
        dispatch_sync(queue, ^{
            NSLog(@"%ld ------ %@", (long)i,  [NSThread currentThread]);
        });
    }
    NSLog(@"I am here %@", [NSThread currentThread]);
}

点击屏幕获取打印:

2017-01-10 22:12:34.551 GCD-01[13537:1337073] 0 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.551 GCD-01[13537:1337073] 1 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.551 GCD-01[13537:1337073] 2 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.552 GCD-01[13537:1337073] 3 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.552 GCD-01[13537:1337073] 4 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.552 GCD-01[13537:1337073] 5 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.552 GCD-01[13537:1337073] 6 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.553 GCD-01[13537:1337073] 7 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.553 GCD-01[13537:1337073] 8 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.553 GCD-01[13537:1337073] 9 ------ <NSThread: 0x6180000764c0>{number = 1, name = main}
2017-01-10 22:12:34.553 GCD-01[13537:1337073] I am here <NSThread: 0x6180000764c0>{number = 1, name = main}

结果:由打印信息可以看出,同步任务不会创建新的线程,由于只有一个线程,即使是并行队列可以同时获取多个任务,最终也会按照顺序执行,因为只有一条线程。

并行队列异步执行

- (void)gcdBase4 {
    
    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_CONCURRENT);
    for (NSInteger i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"%ld ------ %@", (long)i,  [NSThread currentThread]);
        });
    }
    NSLog(@"I am here %@", [NSThread currentThread]);
}

这次我多次点击屏幕时,获得以下输出:

2017-01-10 22:18:15.768 GCD-01[13664:1350605] I am here <NSThread: 0x60000006bcc0>{number = 1, name = main}
2017-01-10 22:18:15.768 GCD-01[13664:1350805] 0 ------ <NSThread: 0x618000070700>{number = 3, name = (null)}
2017-01-10 22:18:15.768 GCD-01[13664:1351252] 1 ------ <NSThread: 0x61800006bf80>{number = 4, name = (null)}
2017-01-10 22:18:15.768 GCD-01[13664:1351253] 2 ------ <NSThread: 0x610000073880>{number = 5, name = (null)}
2017-01-10 22:18:15.768 GCD-01[13664:1351254] 3 ------ <NSThread: 0x61800006afc0>{number = 6, name = (null)}
2017-01-10 22:18:15.768 GCD-01[13664:1351255] 4 ------ <NSThread: 0x6000000725c0>{number = 7, name = (null)}
2017-01-10 22:18:15.768 GCD-01[13664:1351256] 5 ------ <NSThread: 0x61800006a2c0>{number = 8, name = (null)}
2017-01-10 22:18:15.769 GCD-01[13664:1351257] 6 ------ <NSThread: 0x610000073540>{number = 9, name = (null)}
2017-01-10 22:18:15.769 GCD-01[13664:1351258] 7 ------ <NSThread: 0x618000070480>{number = 10, name = (null)}
2017-01-10 22:18:15.769 GCD-01[13664:1350805] 8 ------ <NSThread: 0x618000070700>{number = 3, name = (null)}
2017-01-10 22:18:15.769 GCD-01[13664:1351252] 9 ------ <NSThread: 0x61800006bf80>{number = 4, name = (null)}


2017-01-10 22:18:24.114 GCD-01[13664:1350605] I am here <NSThread: 0x60000006bcc0>{number = 1, name = main}
2017-01-10 22:18:24.115 GCD-01[13664:1351637] 1 ------ <NSThread: 0x610000073940>{number = 12, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351259] 0 ------ <NSThread: 0x60800006e080>{number = 11, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351638] 2 ------ <NSThread: 0x6180000705c0>{number = 13, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351639] 3 ------ <NSThread: 0x61000006f240>{number = 14, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351641] 4 ------ <NSThread: 0x61800006c080>{number = 15, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351643] 5 ------ <NSThread: 0x600000071f80>{number = 16, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351640] 7 ------ <NSThread: 0x600000072ac0>{number = 18, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351644] 6 ------ <NSThread: 0x618000070500>{number = 17, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351637] 8 ------ <NSThread: 0x610000073940>{number = 12, name = (null)}
2017-01-10 22:18:24.115 GCD-01[13664:1351647] 9 ------ <NSThread: 0x610000073540>{number = 19, name = (null)}


2017-01-10 22:18:26.446 GCD-01[13664:1350605] I am here <NSThread: 0x60000006bcc0>{number = 1, name = main}
2017-01-10 22:18:26.446 GCD-01[13664:1351647] 0 ------ <NSThread: 0x610000073540>{number = 19, name = (null)}
2017-01-10 22:18:26.446 GCD-01[13664:1351637] 1 ------ <NSThread: 0x610000073940>{number = 12, name = (null)}
2017-01-10 22:18:26.446 GCD-01[13664:1351644] 2 ------ <NSThread: 0x618000070500>{number = 17, name = (null)}
2017-01-10 22:18:26.446 GCD-01[13664:1351640] 3 ------ <NSThread: 0x600000072ac0>{number = 18, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351643] 4 ------ <NSThread: 0x600000071f80>{number = 16, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351641] 5 ------ <NSThread: 0x61800006c080>{number = 15, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351639] 6 ------ <NSThread: 0x61000006f240>{number = 14, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351638] 7 ------ <NSThread: 0x6180000705c0>{number = 13, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351259] 8 ------ <NSThread: 0x60800006e080>{number = 11, name = (null)}
2017-01-10 22:18:26.447 GCD-01[13664:1351646] 9 ------ <NSThread: 0x610000073d80>{number = 20, name = (null)}



2017-01-10 22:18:26.598 GCD-01[13664:1351646] 0 ------ <NSThread: 0x610000073d80>{number = 20, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1350605] I am here <NSThread: 0x60000006bcc0>{number = 1, name = main}
2017-01-10 22:18:26.598 GCD-01[13664:1351259] 1 ------ <NSThread: 0x60800006e080>{number = 11, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351638] 2 ------ <NSThread: 0x6180000705c0>{number = 13, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351639] 3 ------ <NSThread: 0x61000006f240>{number = 14, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351641] 4 ------ <NSThread: 0x61800006c080>{number = 15, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351643] 5 ------ <NSThread: 0x600000071f80>{number = 16, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351640] 6 ------ <NSThread: 0x600000072ac0>{number = 18, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351644] 7 ------ <NSThread: 0x618000070500>{number = 17, name = (null)}
2017-01-10 22:18:26.598 GCD-01[13664:1351637] 8 ------ <NSThread: 0x610000073940>{number = 12, name = (null)}
2017-01-10 22:18:26.599 GCD-01[13664:1351649] 9 ------ <NSThread: 0x61800006f680>{number = 21, name = (null)}



2017-01-10 22:18:26.734 GCD-01[13664:1351637] 1 ------ <NSThread: 0x610000073940>{number = 12, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351649] 0 ------ <NSThread: 0x61800006f680>{number = 21, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351644] 2 ------ <NSThread: 0x618000070500>{number = 17, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1350605] I am here <NSThread: 0x60000006bcc0>{number = 1, name = main}
2017-01-10 22:18:26.734 GCD-01[13664:1351640] 3 ------ <NSThread: 0x600000072ac0>{number = 18, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351643] 4 ------ <NSThread: 0x600000071f80>{number = 16, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351641] 5 ------ <NSThread: 0x61800006c080>{number = 15, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351639] 6 ------ <NSThread: 0x61000006f240>{number = 14, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351638] 7 ------ <NSThread: 0x6180000705c0>{number = 13, name = (null)}
2017-01-10 22:18:26.734 GCD-01[13664:1351259] 8 ------ <NSThread: 0x60800006e080>{number = 11, name = (null)}
2017-01-10 22:18:26.735 GCD-01[13664:1351646] 9 ------ <NSThread: 0x610000073d80>{number = 20, name = (null)}

结果分析: 由多次点击结果可以确定,异步任务,开启了新线程,并发执行能够拿到多个任务,所以上面会出现任务执行顺序不一致,并且I am here的位置,也可以确定主线程没有被影响。

一个模拟项目中的同步任务

在这里我模拟一个实际开发流程:比如在一个读书的APP中,通常会出现付费下载的情况,当用户在游客模式去浏览,发现到自己喜欢的书籍时,去点击下载,这时候就需要走 登录 -> 支付 -> 下载,这就是一个同步任务,这里有很多网络请求,属于耗时操作,通常我们都在子线程中去完成。在这个任务中,我们将设置一下流程,用户必须先登录,然后同时执行支付和下载任务。对此,实现以下代码:

- (void)gcdSyncTask {
    //创建一个并行队列
    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_CONCURRENT);
    //同步添加 用户登录 任务
    dispatch_sync(queue, ^{
        NSLog(@"用户登录");
    });
    //异步添加 支付任务 可以在子线程中执行
    dispatch_async(queue, ^{
        NSLog(@"支付任务");
    });
    //异步添加 下载任务 可以在子线程中执行
    dispatch_async(queue, ^{
        NSLog(@"下载任务");
    });
}

当点击屏幕获得以下打印:经过多次点击都可以发现,用户登录永远都先执行的,只有用户登录完成后,才会去执行支付和下载任务。实际情况,任务的执行会更加耗时,那么支付和下载的完成顺序也就会不确定

2017-01-10 22:50:53.816 GCD-01[14340:1423863] 用户登录
2017-01-10 22:50:53.816 GCD-01[14340:1423979] 支付任务
2017-01-10 22:50:53.816 GCD-01[14340:1423977] 下载任务

对模拟项目升级

在之前的项目中,所以的点击添加任务都是在主线程中添加的,下面模拟一下在,子线程中添加上述的同步任务会出现什么情况:

- (void)gcdStrongSyncTask {
    //创建一个并行队列
    dispatch_queue_t queue = dispatch_queue_create(myQueue, DISPATCH_QUEUE_CONCURRENT);
    
    //这里讲之前的任务 放到task代码快中
    void (^task)() = ^{
        
        for (NSInteger i = 0; i < 10; i ++) {
            dispatch_sync(queue, ^{
                NSLog(@"%ld ------ %@", (long)i,  [NSThread currentThread]);
            });
        }
        //同步添加 用户登录 任务
        dispatch_sync(queue, ^{
            NSLog(@"用户登录  %@", [NSThread currentThread]);
        });
        //异步添加 支付任务 可以在子线程中执行
        dispatch_async(queue, ^{
            NSLog(@"支付任务   %@", [NSThread currentThread]);
        });
        //异步添加 下载任务 可以在子线程中执行
        dispatch_async(queue, ^{
            NSLog(@"下载任务  %@", [NSThread currentThread]);
        });
    };
    //以异步任务的方式,将task在子线程中去执行,从而完成在子线程中去执行之前的任务
    dispatch_async(queue, task);
    NSLog(@" I come here    %@", [NSThread currentThread]);
}

以下结果是我多次点击之后得到的,我选取其中有代表性的一段,可以发现两点:

2017-01-10 23:05:00.053 GCD-01[14704:1458015]  I come here    <NSThread: 0x60000006e440>{number = 1, name = main}
2017-01-10 23:05:00.053 GCD-01[14704:1458400] 0 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.054 GCD-01[14704:1458400] 1 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.054 GCD-01[14704:1458400] 2 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.055 GCD-01[14704:1458400] 3 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.055 GCD-01[14704:1458400] 4 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.055 GCD-01[14704:1458400] 5 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.056 GCD-01[14704:1458400] 6 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.056 GCD-01[14704:1458400] 7 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.056 GCD-01[14704:1458400] 8 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.056 GCD-01[14704:1458400] 9 ------ <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.057 GCD-01[14704:1458400] 用户登录  <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.057 GCD-01[14704:1458400] 支付任务   <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.057 GCD-01[14704:1458089] 下载任务  <NSThread: 0x61800006dbc0>{number = 5, name = (null)}




2017-01-10 23:05:00.573 GCD-01[14704:1458015]  I come here    <NSThread: 0x60000006e440>{number = 1, name = main}
2017-01-10 23:05:00.573 GCD-01[14704:1458089] 0 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.574 GCD-01[14704:1458089] 1 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.574 GCD-01[14704:1458089] 2 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.574 GCD-01[14704:1458089] 3 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.575 GCD-01[14704:1458089] 4 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.575 GCD-01[14704:1458089] 5 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.575 GCD-01[14704:1458089] 6 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.575 GCD-01[14704:1458089] 7 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.576 GCD-01[14704:1458089] 8 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.576 GCD-01[14704:1458089] 9 ------ <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.576 GCD-01[14704:1458089] 用户登录  <NSThread: 0x61800006dbc0>{number = 5, name = (null)}
2017-01-10 23:05:00.577 GCD-01[14704:1458400] 下载任务  <NSThread: 0x608000070600>{number = 6, name = (null)}
2017-01-10 23:05:00.577 GCD-01[14704:1458089] 支付任务   <NSThread: 0x61800006dbc0>{number = 5, name = (null)}

总结

对于GCD的基本使用,注意以下三点:

上一篇下一篇

猜你喜欢

热点阅读