GCD的介绍
GCD(Grand Central Dispatch)中文名称为“中央调度”或“大中央派发”等,是一个多核编程的解决方法。主要用于优化应用程序支持多核处理器以及其他对称多处理系统。是一个在线程池模式的基础上执行的并行任务。
在iOS开发中, 类似于GCD还有NSThread, NSOperation & NSOperationQueue等。
GCD优点
- GCD会自动利用更多的CPU内核;
- GCD可以用在多核并行运算;
- GCD会自动管理线程的生命周期, 比如创建线程, 调度任务, 销毁线程等操作。
GCD的任务和队列
任务
任务是指放在GCD里的操作, 一般是用Block方式进行。
执行任务的操作有两种, 同步执行和异步执行, 两个的区别就是在是否开启新线程进行操作。
同步执行(sync) : 不会开启新线程, 只会在当前线程进行操作。
异步执行(async): 可以另外开启一个新的线程执行任务。
队列
队列指的是任务队列, 用来存放任务的队列。采用的是先进先出(FIFO)原则。
这里的队列分为两种, 并行队列和串行队列.
并行队列(Concurrent Dispatch Queue): 可以让多个任务同时执行, 如果用到并行队列的话, 是会自动开启多个线程同时执行任务。
串行队列(Serial Dispatch Queue): 任务一个接一个的执行, 完成了前面的任务再执行后面的任务。
注意: 并行队列只有在异步执行(dispatch_async)才有效。
GCD的使用
1.创建队列
可以使用dispatch_queue_create来创建对象
dispatch_queue_create(const char * _Nullable label, dispatch_queue_attr_t _Nullable attr)
第一个参数: 队列的唯一标识符,表现形式可以是字符串如:“Queue”;
第二个参数: 队列的类型, 串行队列(DISPATCH_QUEUE_SERIAL)或 并行队列(DISPATCH_QUEUE_CONCURRENT)
// 创建串行队列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL);
// 创建并行队列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);
常用的,并行队列可以用全局并行队列dispatch_get_global_queue(long identifier, unsigned long flags)创建。
第一个参数: 队列的优先级, 一般都是用DISPATCH_QUEUE_PRIORITY_DEFAULT.
第二个参数: 一般都是用0.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.创建任务
// 创建同步执行任务
dispatch_sync(queue, ^{
// service code
});
// 创建异步执行任务
dispatch_async(queue, ^{
// service code
});
队列和任务的组合:
同步执行(sync) | 异步执行(async) | |
---|---|---|
并行队列 | 不开启新线程, 串行方式执行任务 | 开启新线程, 并行方式执行任务 |
串行队列 | 不开启新线程, 串行方式执行任务 | 开启一条新线程, 串行方式执行任务 |
主队列 | 不开启新线程, 串行方式执行任务 | 不开启新线程, 串行方式执行任务 |
CGD的基本使用
-
并行队列同步执行
- (void)dispatch_sync_queue_concurrent {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:34:57.299 GCDTest[1974:149023] Start working on a task
2017-08-12 14:34:57.299 GCDTest[1974:149023] The first task of the current thread:{number = 1, name = main}
2017-08-12 14:34:57.299 GCDTest[1974:149023] The second task of the current thread:{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] The third task of the current thread:{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] Finish working on a task
- 当前的线程都为同一条(main线程),而且线程数只有1;
- 从执行顺序上, 并行队列同步执行是一个任务一个任务的去执行的。
-
并行队列异步执行
- (void)dispatch_async_queue_concurrent {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:35:33.395 GCDTest[1974:149023] Start working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149163] The first task of the current thread:{number = 3, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149997] The second task of the current thread:{number = 4, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149998] The third task of the current thread:{number = 5, name = (null)}
- 当前的线程数有多条, 而且线程的名字未知;
- 从时间上来看, 几乎都是在同一时间执行任务的;
- 并行队列异步执行的组合除了在主队列上执行, 还会另外开启多几条线程来并行执行任务。
-
串行队列同步执行
- (void)dispatch_sync_queue_serial {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:08.965 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:08.966 GCDTest[1974:149023] The first task of the current thread:{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The second task of the current thread:{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The third task of the current thread:{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] Finish working on a task
- 从执行顺序上,串行队列同步执行是一个任务一个任务的去执行的。
-
串行队列异步执行
- (void)dispatch_async_queue_serial {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:22.973 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:22.973 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:36:22.974 GCDTest[1974:149163] The first task of the current thread:{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The second task of the current thread:{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The third task of the current thread:{number = 3, name = (null)}
- 开启新线程来执行任务,由于是串行队列,所以任务还是一个接着一个来执行。
- 任务并不是一下子就开始执行的,是需要将任务都添加到队列里,然后才开始同步执行。
-
主队列同步执行
- (void)dispatch_sync_queue_main {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:43.542 GCDTest[1974:149023] Start working on a task
- 所有放在主队列里执行的任务都会放到主线程里执行;
运行的时候出现异常, 系统崩溃~~~
同步执行是一个一个任务去执行的,当主线程还在执行 [self dispatch_sync_queue_main] 的时候,往主线程里添加任务,这个时候就会出现异常现象,我们称之为卡线程。
-
主队列异步执行
- (void)dispatch_async_queue_main {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:37:08.303 GCDTest[2047:151940] Start working on a task
2017-08-12 14:37:08.303 GCDTest[2047:151940] Finish working on a task
2017-08-12 14:37:08.304 GCDTest[2047:151940] The first task of the current thread:{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The second task of the current thread:{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The third task of the current thread:{number = 1, name = main}
- 所有放在主队列里执行的任务都会放到主线程里执行。
- 虽然用的是异步执行,具备了开启新线程的能力,但是由于这是主队列,所以所有的任务都是在主线程中,任务也是一个接着一个顺序执行。
- 任务并不是马上就执行的,而是把所有任务都添加到队列里之后再执行。