Grand Central Dispatch(GCD)
是 Apple 开发的一个多核编程的较新的解决方法。
它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。
它是一个在线程池模式的基础上执行的并发任务。
在Mac OS X Snow Leopard 10.6
中首次推出,也可在iOS 4
及以上版本使用。
-
dispatch_queue: serial / concurrent (main/global)
-
dispatch_sync / dispatch_async
-
dispatch_barrier: sync / async (用在自定义并行队列中)
-
dispatch_group: create async enter leave wait notify
-
dispatch_once
-
dispatch_after
-
dispatch_source timer
-
dispatch_semaphore
-
dispatch_apply
dispatch_queue_create
创建和获取队列
// 创建并发队列
dispatch_queue_t queue = dispatch_queue_create("com.mine.concurrent", DISPATCH_QUEUE_CONCURRENT);
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.mine.serial", DISPATCH_QUEUE_SERIAL);
// 获取全局队列(并发)
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 获取主队列(串行)
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync
同步执行任务
for (int i = 0; i < 10; i++) {
// 同步步执行任务
dispatch_sync(queue, ^{
sleep(1);
NSLog(@"task %d -- %@", i, NSThread.currentThread);
});
// 同步调用函数
dispatch_sync_f(queue, &i, somefunc);
}
// 定义调用的函数
void somefunc(void *_Nullable context) {
sleep(1);
int *i = (int *)context;
// context 可以传 ViewController 对象
// ViewController *vc = (__bridge ViewController *)(context);
NSLog(@"this is some function. -- %d", *i);
}
dispatch_async
异步执行任务
for (int i = 0; i < 10; i++) {
// 异步执行任务
dispatch_async(queue, ^{
sleep(1);
NSLog(@"task %d -- %@", i, NSThread.currentThread);
});
// 异步调用函数
dispatch_async_f(queue, &i, somefunc);
}
// 定义调用的函数
void somefunc(void *_Nullable context) {
sleep(1);
int *i = (int *)context;
// context 可以传 ViewController 对象
// ViewController *vc = (__bridge ViewController *)(context);
NSLog(@"this is some function. -- %d", *i);
}
dispatch_barrier
栅栏:在它之前的任务执行结束后它才执行,它之后的任务需要等它执行完成之后才会执行。
注意:queue
不能是dispatch_get_global_queue
(全局的并发队列)
for (int i = 0; i < 10; i++) {
dispatch_barrier_async(queue, ^{
sleep(1);
NSLog(@"barrier task %d -- %@", i, NSThread.currentThread);
});
}
dispatch_group
队列组:等多个异步任务都执行完后,再执行某个任务。
dispatch_barrier
也可以实现。
dispatch_group_t group = dispatch_group_create();
// 方式一
for (int i = 0; i < 10; i++) {
dispatch_group_async(group, queue, ^{
sleep(2);
NSLog(@"task %d -- %@", i, NSThread.currentThread);
});
}
// 方式二
for (int i = 0; i < 10; i++) {
dispatch_group_enter(group);
dispatch_async(queue, ^{
sleep(3);
NSLog(@"task %d -- %@", i, NSThread.currentThread);
dispatch_group_leave(group);
});
}
// dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_FOREVER, 0));
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5));
dispatch_group_notify(group, queue, ^{
NSLog(@"group notify -- %@", NSThread.currentThread);
});
dispatch_once
只会执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"do once");
});
dispatch_after
延迟执行队列任务
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * 2)), queue, ^{
NSLog(@"after ");
});
dispatch_source timer
GCD Timer
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1*NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"timer -- %@", NSThread.currentThread);
});
dispatch_resume(timer);
self->timer = timer;
dispatch_semaphore
信号量
dispatch_semaphore_create
: 创建信号量,设定信号量的初始值。
dispatch_semaphore_signal
: 对信号量的值进行加1操作。
dispatch_semaphore_wait
: 信号量的值=0时,函数不返回,会一直等待,阻塞当前线程;信号量的值>=1时,对信号量的值减1,继续执行当前任务。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
sleep(1);
NSLog(@"task 1 -- %@", NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
});
// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
sleep(3);
NSLog(@"task 2");
dispatch_semaphore_signal(semaphore);
});
// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
sleep(2);
NSLog(@"task 3");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semaphore);
dispatch_apply
快速迭代,常用于并发队列中。
无论是在串行队列,还是并发队列中,dispatch_apply
都会等待全部任务执行完毕
NSLog(@"apply---begin");
dispatch_apply(10, queue, ^(size_t i) {
sleep(1);
NSLog(@"i -- %zu -- %@", i, NSThread.currentThread);
});
NSLog(@"apply---end");
网友评论