介绍

Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统。这建立在任务并行执行的线程池模式的基础上的。它首次发布在Mac OS X 10.6 ,iOS 4及以上也可用。基于FIFO队列,保证先进先出。

dispatch queue分为下面三种:

  1. Serial
    又称为private dispatch queues,同时只执行一个任务。
  2. Concurrent
    又称为global dispatch queue,可以并发地执行多个任务。
  3. Main dispatch queue
    它是全局可用的serial queue,它是在应用程序主线程上执行任务的。

1. 简单的使用

1
2
3
4
5
6
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
// 耗时的操作TODO
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程更新界面TODO
});
});

2. 获取一个queue

  1. 获取系统queue。 前者是优先级,有三个优先级, 后者是flag标识

    1
    dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  2. 获取一个主线程queue

    1
    dispatch_queue_t mainQ = dispatch_get_main_queue();
  3. 新建一个queue。前者是标记,后者是类型,串行并行

    1
    dispatch_queue_t queue = dispatch_queue_create("com.d3.tttt", DISPATCH_QUEUE_CONCURRENT);

3. 任务组

当所有任务都完成,会执行通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);

三个任务都执行完成会执行通知,打印updateui。

三个任务都执行完成会执行通知,打印updateui。

4.常用方法

4.1 只执行一次dispatch_once

1
2
3
4
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
NSLog(@"代码块只执行了一次");
});

4.2 在两个线程之间执行一段代码,并且分离了线程,不会使它们同时执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
dispatch_barrier_async(queue,^(void){});
//并行队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程一:%d",i);
}
});


dispatch_async(concurrentQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程二:%d",i);
}
});

dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"我隔开了你们");
});

dispatch_async(concurrentQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程三:%d",i);
}
});

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2015-09-07 16:00:17.162 test[26681:3530825] 线程二:0
2015-09-07 16:00:17.162 test[26681:3530821] 线程一:0
2015-09-07 16:00:17.162 test[26681:3530825] 线程二:1
2015-09-07 16:00:17.162 test[26681:3530821] 线程一:1
2015-09-07 16:00:17.162 test[26681:3530825] 线程二:2
2015-09-07 16:00:17.162 test[26681:3530821] 线程一:2
2015-09-07 16:00:17.163 test[26681:3530825] 线程二:3
2015-09-07 16:00:17.163 test[26681:3530821] 线程一:3
2015-09-07 16:00:17.163 test[26681:3530825] 线程二:4
2015-09-07 16:00:17.163 test[26681:3530821] 线程一:4
2015-09-07 16:00:17.163 test[26681:3530821] 我隔开了你们
2015-09-07 16:00:17.163 test[26681:3530821] 线程三:0
2015-09-07 16:00:17.163 test[26681:3530821] 线程三:1
2015-09-07 16:00:17.163 test[26681:3530821] 线程三:2
2015-09-07 16:00:17.163 test[26681:3530821] 线程三:3
2015-09-07 16:00:17.163 test[26681:3530821] 线程三:4

4.3 一段时间后执行

1
2
3
4
5
6
7
8
dispatch_after(dispatch_time_t time,queue,^(void){});

NSLog(@"begin : %@",[NSDate date]);
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 10);

dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"after : %@",[NSDate date]);
});

结果:

1
2
2015-09-07 16:12:35.311 test[26979:3612698] begin : 2015-09-07 08:12:35 +0000
2015-09-07 16:12:46.311 test[26979:3612888] after : 2015-09-07 08:12:46 +0000

4.4暂停线程队列。只是暂停未开始的线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dispatch_suspend/dispatch_resume,通过计数方式
//并行队列,
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程一:%d",i);
}
});


dispatch_suspend(concurrentQueue);

dispatch_async(concurrentQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程二:%d",i);
}
});

sleep(4);
dispatch_resume(concurrentQueue);

结果,4秒后恢复:

1
2
3
4
5
6
7
8
9
10
2015-09-07 16:27:25.539 test[27299:3702436] 线程一:0
2015-09-07 16:27:25.540 test[27299:3702436] 线程一:1
2015-09-07 16:27:25.540 test[27299:3702436] 线程一:2
2015-09-07 16:27:25.540 test[27299:3702436] 线程一:3
2015-09-07 16:27:25.540 test[27299:3702436] 线程一:4
2015-09-07 16:27:29.540 test[27299:3702436] 线程二:0
2015-09-07 16:27:29.540 test[27299:3702436] 线程二:1
2015-09-07 16:27:29.540 test[27299:3702436] 线程二:2
2015-09-07 16:27:29.540 test[27299:3702436] 线程二:3
2015-09-07 16:27:29.541 test[27299:3702436] 线程二:4