GCD
任务调度,由系统维护线程池,分配执行线程,简单高效,队列只负责任务的调度,执行在线程中
基本知识点
队列的特点:FIFO.(不管是串行的还是并发的,任务是执行顺序都是按照FIFO规则)
串行队列:任务按照顺序被调度,前一个任务不执行完毕,队列不会调度
并发队列:只要有空闲的线程,队列就会调度当前任务。
主队列:专门用来在主线程调度任务的队列
全局队列:系统提供的并发队列
同步执行:不会开启新的线程,任务按顺序执行
异步执行:会开启新的线程,任务可以并发的执行
并行:多个任务同时执行
并发:多个任务“同时”执行
根据队列的类型和执行方式,划分以下组合 (同步任务):
- 串行队列同步执行:依次执行。
- 串行队列异步执行:串行队列的特点,前一个任务不执行完毕,队列不会调度新的任务,依次执行。
- 并行队列同步执行:同步执行不会开启新的线程,依次执行。
- 并行队列异步执行:并发执行
常见方法
dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT/DISPATCH_QUEUE_SERIAL)
dispatch_sync(queue, ^{})
dispatch_async(queue, ^{})
dispatch_get_main_queue()
dispatch_get_global_queue(0, 0);
dispatch_once()
dispatch_barrier_async:用于等待前面的任务执行完毕后自己才执行,而它后面的任务需等待它完成之后才执行。
dispatch_queue_t queue = dispatch_queue_create("Database_Queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"reading data1");
});
dispatch_async(queue, ^{
NSLog(@"reading data2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"writing data1");
[NSThread sleepForTimeInterval:1];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"reading data3");
});
dispatch_queue_set_specific:为队列设置唯一的标志,可用于检查当前之在的queue,避免死锁
dispatch_get_specific:获取队列标志
dispatch_apply:在指定的dispatch queue中运行block任务n次,如果队列是并发队列,则会并发执行block任务,同步调用,block任务执行n次后才返回。
dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(5, queue, ^(size_t i) {
NSLog(@"do a job %zu times",i+1);
});
dispatch_block_t:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create_with_qos_class(0, QOS_CLASS_USER_INITIATED, -1, ^{
NSLog(@"do something with QoS");
});
dispatch_async(queue, block);
dispatch_block_wait:等待前面的任务执行完毕
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"before sleep");
[NSThread sleepForTimeInterval:1];
NSLog(@"after sleep");
});
dispatch_async(queue, block);
//等待前面的任务执行完毕
dispatch_block_wait(block, DISPATCH_TIME_FOREVER);
NSLog(@"coutinue");
dispatch_block_notify:当观察的某个block执行结束之后立刻通知提交另一特定的block到指定的queue中执行
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t previousBlock = dispatch_block_create(0, ^{
NSLog(@"previousBlock begin");
[NSThread sleepForTimeInterval:1];
NSLog(@"previousBlock done");
});
dispatch_async(queue, previousBlock);
dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
NSLog(@"notifyBlock");
});
//当previousBlock执行完毕后,提交notifyBlock到global queue中执行
dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);
dispatch_block_cancel(iOS 8):取消提交到队列中未被调度执行的任务
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block1 = dispatch_block_create(0, ^{
NSLog(@"block1 begin");
[NSThread sleepForTimeInterval:1];
NSLog(@"block1 done");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
NSLog(@"block2 ");
});
dispatch_async(queue, block1);
dispatch_async(queue, block2);
dispatch_block_cancel(block2);
dispatch_group_wait:同步地等待group中所有的block执行完毕后才继续执行,会阻塞当前线程
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
//将任务异步地添加到group中去执行
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
NSLog(@"go on");
只有block1跟block2执行完毕后才会执行dispatch_group_wait后面的内容。
dispatch_group_notify:dispatch_group_wait类似,异步的,不会阻塞该线程
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"done");
});
NSLog(@"go on”);
dispatch_group_enter:对于提交到group中的任务是一个异步任务时,则需要手动处理进入/退出 group的时机
dispatch_group_leave: 成对出现
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{});
Dispatch Semaphore:信号量
//创建一个信号量,初始值为0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"do some job");
sleep(1);
NSLog(@"increase the semaphore");
dispatch_semaphore_signal(sema); //信号值加1
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);//等待直到信号值大于等1(信号值减1)
dispatch timer:通常配合dispatch_after使用,完成一些延时的任务:
//延迟5秒后调度
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"do job afer 5 seconds");
});
dispatch_source:监听系统底层对象(文件描述符、Mach端口、信号量等),当这些对象有事件产生时会自动把事件的处理block函数提交到dispatch队列中执行
DISPATCH_SOURCE_TYPE_DATA_ADD 变量增加
DISPATCH_SOURCE_TYPE_DATA_OR 变量ORDISPATCH_SOURCE_TYPE_MACH_SEND Mach端口发送
DISPATCH_SOURCE_TYPE_MACH_RECV Mach端口接收
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE 内存压力情况变化
DISPATCH_SOURCE_TYPE_PROC 与进程相关的事件
DISPATCH_SOURCE_TYPE_READ 可读取文件映像
DISPATCH_SOURCE_TYPE_SIGNAL 接收信号
DISPATCH_SOURCE_TYPE_TIMER 定时器事件
DISPATCH_SOURCE_TYPE_VNODE 文件系统变更
DISPATCH_SOURCE_TYPE_WRITE 可写入文件映像
@property (nonatomic)dispatch_source_t timerSource;
dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
uint64_t interval = 2 * NSEC_PER_SEC;
dispatch_source_set_timer(_timerSource,DISPATCH_TIME_NOW, interval , 0);
//设置事件的处理handler
dispatch_source_set_event_handler(_timerSource, ^{
NSLog(@"receive time event");
//if (done)
// dispatch_source_cancel(_timerSource);
});
dispatch_resume(_timerSource);