iOS 多线程iOS重修

iOS多线程--GCD

2017-08-30  本文已影响121人  9d8c8692519b

1. GCD简介

GCD全称Grand Central Dispatch,我们通俗的翻译叫牛逼的中心调度。

GCD简化了多线程的实现,有以下优点:

GCD可用于多核的并行运算;
GCD会自动利用更多的CPU内核(比如双核、四核);
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程);
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码。
GCD抽象层次最高,使用也简单,因此,苹果也推荐使用GCD。但是在这里也需要注意的是使用GCD的场景如果很复杂,就有非常大的可能遇到死锁问题

两个核心概念

1、队列:队列负责管理开发者提交的任务,以先进先出(FIFO)的方式来处理任务。
a.)串行队列:每次只执行一个任务,当前一个任务执行完成后才执行下一个任务
b.)并行队列:多个任务并发执行,所以先执行的任务可能最后才完成(因为具体的执行过程导致)

2、任务:任务就是开发者提供给队列的工作单元,这些任务将会提交给队列底层维护的线程池,因此这些任务将会以多线程的方式执行。

关于同步异步、串行并行和线程的关系,下面通过一个表格来总结
关系.jpg

可以看到,同步方法不一定在本线程,异步方法方法也不一定新开线程(考虑主队列)。
由上图我们可以得出我们有3种队列,2种任务执行方式,那么我们就有了6种不同的组合方式。我们接下来将逐一说明。这6种不同的组合方式是 :

1.并行队列 + 同步执行
2.并行队列 + 异步执行
3.串行队列 + 同步执行
4.串行队列 + 异步执行
5.主队列 + 同步执行
6.主队列 + 异步执行

2. GCD的使用

2.1 队列的创建方法

可以使用dispatch_queue_create来创建对象,需要传入两个参数,第一个参数表示队列的唯一标识符,用于DEBUG,可为空;第二个参数用来识别是串行队列还是并行队列。DISPATCH_QUEUE_SERIAL表示串行队列,DISPATCH_QUEUE_CONCURRENT表示并行队列。如:

// 串行队列的创建方法
dispatch_queue_t queue= dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_SERIAL);
// 并行队列的创建方法
dispatch_queue_t queue= dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
// 全局并行队列。GCD默认提供了全局的并行队列,需要传入两个参数。第一个参数表示队列优先级,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT。第二个参数暂时没用,用0即可
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    });

2.2 任务的创建方法

// 同步执行任务创建方法
dispatch_sync(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);    // 执行任务
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);    // 执行任务
});

到这里我们已经基本学会GCD的使用由队列任务两部分组成。而上面我们提到6种不同的组合方式,一起往下看吧!

2.3 并行队列 + 同步执行

//MARK: 并行队列 + 同步执行
- (void) syncConcurrent
{
    NSLog(@"begin-- 并行队列 + 同步执行");
    dispatch_queue_t queue= dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end-- 并行队列 + 同步执行");
}

输出结果如下:
2017-08-30 16:05:21.909 Multi-thread_GCD[27831:1880116] begin-- 并行队列 + 同步执行
2017-08-30 16:05:21.909 Multi-thread_GCD[27831:1880116] 1------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] 1------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] 2------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] 2------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] 3------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] 3------<NSThread: 0x618000068800>{number = 1, name = main}
2017-08-30 16:05:21.910 Multi-thread_GCD[27831:1880116] end-- 并行队列 + 同步执行

并行队列 + 同步执行 中可以看到:
1.所有任务都是在主线程中执行的。由于只有一个线程,所以任务只能一个一个执行。
2.同时我们还可以看到,所有任务都在打印的begin--和end--之间,这说明任务是添加到队列中马上执行的。

2.4 并行队列 + 异步执行

//MARK: 并行队列 + 异步执行
- (void) asyncConcurrent
{
    NSLog(@"begin-- 并行队列 + 异步执行");
    dispatch_queue_t queue= dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    
    NSLog(@"end-- 并行队列 + 异步执行");
}

输出结果如下:
2017-08-30 16:10:50.689 Multi-thread_GCD[27878:1882329] begin-- 并行队列 + 异步执行
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882329] end-- 并行队列 + 异步执行
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882376] 3------<NSThread: 0x610000075580>{number = 5, name = (null)}
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882378] 1------<NSThread: 0x608000071140>{number = 3, name = (null)}
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882393] 2------<NSThread: 0x61800006f3c0>{number = 4, name = (null)}
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882376] 3------<NSThread: 0x610000075580>{number = 5, name = (null)}
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882378] 1------<NSThread: 0x608000071140>{number = 3, name = (null)}
2017-08-30 16:10:50.690 Multi-thread_GCD[27878:1882393] 2------<NSThread: 0x61800006f3c0>{number = 4, name = (null)}

并行队列 + 异步执行 中可以看出:
1.除了主线程,又开启了3个线程,并且任务是交替着同时执行的。
2.另一方面可以看出,所有任务是在打印的begin-- 和end-- 之后才开始执行的。说明任务不是马上执行,而是将所有任务添加到队列之后才开始异步执行。

2.5 串行队列 + 同步执行

//MARK: 串行队列 + 同步执行
- (void) syncSerial
{
    NSLog(@"begin-- 串行队列 + 同步执行");
    dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end-- 串行队列 + 同步执行");
}

输出结果如下:
2017-08-30 16:16:25.901 Multi-thread_GCD[27929:1884874] begin-- 串行队列 + 同步执行
2017-08-30 16:16:25.901 Multi-thread_GCD[27929:1884874] 1------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.901 Multi-thread_GCD[27929:1884874] 1------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.902 Multi-thread_GCD[27929:1884874] 2------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.902 Multi-thread_GCD[27929:1884874] 2------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.902 Multi-thread_GCD[27929:1884874] 3------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.902 Multi-thread_GCD[27929:1884874] 3------<NSThread: 0x608000077100>{number = 1, name = main}
2017-08-30 16:16:25.902 Multi-thread_GCD[27929:1884874] end-- 串行队列 + 同步执行

串行队列 + 同步执行 可以看出:
1.所有任务都是在主线程中执行的,并没有开启新的线程。而且由于串行队列,所以按顺序一个一个执行。
2.同时我们还可以看到,所有任务都在打印的begin-- 和end-- 之间,这说明任务是添加到队列中马上执行的。

2.6 串行队列 + 异步执行

输出结果如下:
2017-08-30 16:18:41.108 Multi-thread_GCD[27960:1886018] begin-- 串行队列 + 异步执行
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886018] end-- 串行队列 + 异步执行
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 1------<NSThread: 0x6100002625c0>{number = 3, name = (null)}
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 1------<NSThread: 0x6100002625c0>{number = 3, name = (null)}
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 2------<NSThread: 0x6100002625c0>{number = 3, name = (null)}
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 2------<NSThread: 0x6100002625c0>{number = 3, name = (null)}
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 3------<NSThread: 0x6100002625c0>{number = 3, name = (null)}
2017-08-30 16:18:41.109 Multi-thread_GCD[27960:1886059] 3------<NSThread: 0x6100002625c0>{number = 3, name = (null)}

串行队列 + 异步执行 可以看出:
1.开启了一条新线程,但是任务还是串行,所以任务是一个一个执行。
2.另一方面可以看出,所有任务是在打印的begin-- 和end-- 之后才开始执行的。说明任务是将所有任务添加到队列之后才开始同步执行,而不是马上执行。

2.7 主队列 + 同步执行

//MARK: 主队列 + 同步执行   造成死锁  main_queue正在处理syncMain  而syncMain方法中又有同步事件要处理  造成相互等待
- (void)syncMain
{
    NSLog(@"begin-- 主队列 + 同步执行");
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end-- 主队列 + 同步执行");
}

输出结果如下:
2017-08-30 16:23:09.054 Multi-thread_GCD[28004:1887995] begin-- 主队列 + 同步执行

这时候,我们惊奇的发现,在主线程中使用主队列 + 同步执行,任务不再执行了,而且end-- 也没有打印。这是为什么呢?

这是因为我们在主线程中执行这段代码。我们把任务放到了主队列中,也就是放到了主线程的队列中。而同步执行有个特点,就是对于任务是立马执行的。那么当我们把第一个任务放进主队列中,它就会立马执行。但是主线程现在正在处理syncMain方法,所以任务需要等syncMain执行完才能执行。而syncMain执行到第一个任务的时候,又要等第一个任务执行完才能往下执行第二个和第三个任务。

那么,现在的情况就是syncMain方法和第一个任务都在等对方执行完毕。这样大家互相等待,所以就卡住了,所以我们的任务执行不了,而且syncMain---end也没有打印。

要是如果不再主线程中调用,而在其他线程中调用会如何呢?

dispatch_queue_t queue = dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [self syncMain];
    });

输出结果如下:
2017-08-30 16:25:58.949 Multi-thread_GCD[28057:1889723] begin-- 主队列 + 同步执行
2017-08-30 16:25:58.953 Multi-thread_GCD[28057:1889680] 1------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.953 Multi-thread_GCD[28057:1889680] 1------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.954 Multi-thread_GCD[28057:1889680] 2------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.954 Multi-thread_GCD[28057:1889680] 2------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.955 Multi-thread_GCD[28057:1889680] 3------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.955 Multi-thread_GCD[28057:1889680] 3------<NSThread: 0x6080000680c0>{number = 1, name = main}
2017-08-30 16:25:58.955 Multi-thread_GCD[28057:1889723] end-- 主队列 + 同步执行

在其他线程中使用 主队列 + 同步执行 可以看出:
1.所有任务都是在主线程中执行的,并没有开启新的线程。而且由于主队列是串行队列,所以按顺序一个一个执行。
2.同时我们还可以看到,所有任务都在打印的begin-- 和end-- 之间,这说明任务是添加到队列中马上执行的。

2.8 主队列 + 异步执行

//MARK: 主队列 + 异步执行
- (void)asyncMain
{
    NSLog(@"begin-- 主队列 + 异步执行");
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 2; i++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    NSLog(@"end-- 主队列 + 异步执行");
}

输出结果如下:
2017-08-30 16:35:00.918 Multi-thread_GCD[29770:1898088] begin-- 主队列 + 异步执行
2017-08-30 16:35:00.919 Multi-thread_GCD[29770:1898088] end-- 主队列 + 异步执行
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 1------<NSThread: 0x60800007fd40>{number = 1, name = main}
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 1------<NSThread: 0x60800007fd40>{number = 1, name = main}
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 2------<NSThread: 0x60800007fd40>{number = 1, name = main}
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 2------<NSThread: 0x60800007fd40>{number = 1, name = main}
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 3------<NSThread: 0x60800007fd40>{number = 1, name = main}
2017-08-30 16:35:00.923 Multi-thread_GCD[29770:1898088] 3------<NSThread: 0x60800007fd40>{number = 1, name = main}

我们从 主队列 + 异步执行 发现:
1.所有任务都在主线程中,虽然是异步执行,具备开启线程的能力,但因为是主队列,所以所有任务都在主线程中,并且一个接一个执行。
2.另一方面可以看出,所有任务是在打印的begin-- 和end-- 之后才开始执行的。说明任务不是马上执行,而是将所有任务添加到队列之后才开始同步执行。
到这里我们基本可以弄懂了难理解、绕来绕去的队列+任务
接下来,我们来看看——GCD的其他方法

3. GCD的其他方法

3.1 GCD的栅栏方法 (dispatch_barrier_async)

<一>、什么是dispatch_barrier_async函数
毫无疑问,dispatch_barrier_async函数的作用与barrier的意思相同,在进程管理中起到一个栅栏的作用,它等待所有位于barrier函数之前的操作执行完毕后执行,并且在barrier函数执行之后,barrier函数之后的操作才会得到执行,该函数需要同dispatch_queue_create函数生成的concurrent Dispatch Queue队列一起使用。

<二>、dispatch_barrier_async函数的作用
1.实现高效率的数据库访问和文件访问
2.避免数据竞争

- (void) asyncbarrier
{
  //同dispatch_queue_create函数生成的concurrent Dispatch Queue队列一起使用
    dispatch_queue_t queue = dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });
   
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });
}

输出结果:1 2 --> barrier -->3 4 其中12 与 34 由于并行处理先后顺序不定

3.2 GCD只执行一次 ( dispatch_once)

我们在创建单例、或者有整个程序运行过程中只执行一次的代码时,我们就用到了GCD的dispatch_once方法。使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次。

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 只执行1次的代码(这里面默认是线程安全的)
});

3.3 GCD任务组 ( dispatch_group)

了解完队列之后,很自然的会有一个想法:我们怎么知道所有任务都已经执行完了呢?
在单个串行队列中,这个不是问题,因为只要把回调block添加到队列末尾即可。但是对于并行队列,以及多个串行、并行队列混合的情况,就需要使用dispatch_group了。

这里需要指出dispatch_group_wait方法是一个很有用的方法,它的完整定义如下:

 dispatch_group_wait(<#dispatch_group_t  _Nonnull group#>, <#dispatch_time_t timeout#>)

第一个参数表示要等待的group,第二个则表示等待时间。返回值表示经过指定的等待时间,属于这个group的任务是否已经全部执行完,如果是则返回0,否则返回非0。
第二个dispatch_time_t类型的参数还有两个特殊值:DISPATCH_TIME_NOWDISPATCH_TIME_FOREVER
前者表示立刻检查属于这个group的任务是否已经完成,后者则表示一直等到属于这个group的任务全部完成。
dispatch_group_wait代码使用示例

- (void)groupSync
{
    dispatch_queue_t disqueue =  dispatch_queue_create("mytest.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t disgroup = dispatch_group_create();
    dispatch_group_async(disgroup, disqueue, ^{
        NSLog(@"任务一完成");
    });
    dispatch_group_async(disgroup, disqueue, ^{
        sleep(9);
        NSLog(@"任务二完成");
    });
    dispatch_group_notify(disgroup, disqueue, ^{
        NSLog(@"dispatch_group_notify 执行");
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        dispatch_group_wait(disgroup, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
        NSLog(@"dispatch_group_wait 结束");
    });
}

由上面的示例可以看出:
向group中放入两个任务(准确讲是将任务加入到了并行队列disqueue中执行,然后队列和group关联当队列上任务执行完毕时group会进行同步),第二个任务会等待8秒所以第一个任务会先完成;会先打印任务一完成再打印任务二完成,当两个任务都完成时dispatch_group_notify中的block会执行;会接着打印dispatch_group_notify 执行;dispatch_group_wait设置了超时时间为5秒所以它会在5秒后停止等待打印dispatch_group_wait 结束(任务二会等待9秒所以它会在任务二完成前打印);
输出结果:任务一完成 --> dispatch_group_wait 结束 --> 任务二完成 --> dispatch_group_notify 执行

有时候我们会有这样的需求:分别异步执行2个耗时操作,然后当2个耗时操作都执行完毕后再回到主线程执行操作。这时候我们也可以用dispatch_group。dispatch_group通常有两种用法
我们可以先把任务放到队列中,然后将队列放入队列组中。
调用队列组的dispatch_group_notify回到主线程执行操作。具体如下:

用法一:
dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //执行1个耗时
        NSLog(@"Time_1");
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //执行1个耗时
        NSLog(@"Time_2");
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //执行1个耗时
        NSLog(@"Time_3");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //界面刷新
        NSLog(@"任务均完成,刷新界面");
    });

用法二: 以耗时的网络请求操作为例
dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求1
        [网络请求:{
        成功:dispatch_group_leave(group);
        失败:dispatch_group_leave(group);
}];
    });
    dispatch_group_enter;
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求2
        [网络请求:{
        成功:dispatch_group_leave;
        失败:dispatch_group_leave;
}];
    });
    dispatch_group_enter(group);
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求3
        [网络请求:{
        成功:dispatch_group_leave(group);
        失败:dispatch_group_leave(group);
}];
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //界面刷新
        NSLog(@"任务均完成,刷新界面");
    });
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

方法二中需要注意:
使用dispatch_group_enter(group)和dispatch_group_leave(group),这种方式使用更为灵活,enter和leave必须配合使用,有几次enter就要有几次leave,否则group会一直存在。当所有enter的block都leave后,会执行dispatch_group_notify的block。

3.4 GCD的延时执行方法 (dispatch_after)

当我们需要延迟执行一段代码时,就需要用到GCD的dispatch_after方法。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 3秒后异步执行这里的代码
   NSLog(@"run-----");
});

3.5 GCD的快速迭代方法 (dispatch_apply)

比如说遍历0~99这100个数字,通常我们会用for循环遍历,但是GCD给我们提供了快速迭代的方法dispatch_apply,使我们可以同时遍历。for循环的做法是每次取出一个元素,逐个遍历。dispatch_apply可以同时遍历多个数字。代码实现如下:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(100, queue, ^(size_t index) {
    NSLog(@"%zd------%@",index, [NSThread currentThread]);
});

GCD到这里,我们也就结束了。虽然还有很多很多想说的!
上面的示例都很简单,后续会完善示例的源码链接。
彻底学会多线程系列其他内容会后续继续整理,陆续与大家见面。喜欢就多关注我

你可能还要示例源码 在这里 源码
您可能还对 iOS多线程--GCD 感兴趣
您可能还对 iOS多线程--NSOperation 感兴趣
您可能还对 iOS多线程--NSThread 感兴趣

上一篇 下一篇

猜你喜欢

热点阅读