dispatch_queue_t
- 获得主队列
dispatch_queue_t main_queue = dispatch_get_main_queue();
-
创建串行队列
dispatch_queue_t serial_queue = dispatch_queue_create(“name”, DISPATCH_QUEUE_SERIAL);
-
创建并行队列
dispatch_queue_t concurrent_queue = dispatch_queue_create(“name”, DISPATCH_QUEUE_CONCURRENT);
-
获取全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_set_target_queue
dispatch_set_target_queue 1、指定 Dispatch Queue 执行优先级;2、设置执行阶层
dispatch_after
dispatch_after指定时间后将任务追加到主队列中。所谓延迟提交,不是延迟执行。因此严格来说这个时间并不是绝对准确的。
dispatch_semaphore_t
dispatch_semaphore_t可以更细的控制资源。在多线程中很经常当做‘锁’使用,例:
// 创建一个 Semaphore 并初始化信号的总量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
// 使总信号量减 1,信号总量小于 0 时就会一直等待(阻塞所在线程)
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//do.....
// 发送一个信号,让信号总量加 1
dispatch_semaphore_signal(semaphore);
dispatch_once
只会执行一次,经常用于单利创建
+ (instancetype)sharedManager {
static XXManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
dispatch_suspend/dispatch_resume
dispatch_suspend 暂停队列(注意,对于已经开始的任务不会挂起),dispatch_resume恢复队列;
dispatch_group
作用
Dispatch Group 用于整个组的任务都完成时通知你。
这些任务可以是同步的,也可以是异步的,即便在不同的队列也行。
而且在整个组的任务都完成时,Dispatch Group 可以用同步的或者异步的方式通知你.
使用方式
调用队列组的 dispatch_group_async 先把任务放到队列中,然后将队列放入队列组中。
或者使用队列组的 dispatch_group_enter、dispatch_group_leave 组合来实现 dispatch_group_async。
调用队列组的 dispatch_group_notify 回到指定线程执行任务。或者使用 dispatch_group_wait 回到当前线程继续向下执行(会阻塞当前线程)
dispatch_group_notify
监听 group 中任务的完成状态,当所有的任务都执行完成后,追加任务到 group 中,并执行任务
-(void)test_group_01{
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-01:%@",[NSThread currentThread]);
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-02:%@",[NSThread currentThread]);
});
NSLog(@"flag.....");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任务完成");
});
NSLog(@"end.....");
}
//打印
flag.....
task-02:<NSThread: 0x6000010e4400>{number = 5, name = (null)}
end.....
task-01:<NSThread: 0x6000010e4240>{number = 6, name = (null)}
任务完成
dispatch_group_wait
会阻塞当前线程,直到组里面所有的任务都完成或者等到某个超时发生
-(void)test_group_02{
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-01:%@",[NSThread currentThread]);
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-02:%@",[NSThread currentThread]);
});
NSLog(@"flag.....");
//dispatch_group_wait,会阻塞当前线程,直到组里面所有的任务都完成或者等到某个超时发生.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"任务完成");
//打印
flag.....
task-01:<NSThread: 0x600000260980>{number = 4, name = (null)}
task-02:<NSThread: 0x600000260780>{number = 6, name = (null)}
任务完成
}
dispatch_group_enter、dispatch_group_leave
必须保证 dispatch_group_enter 和 dispatch_group_leave 成对出现,否则你可能会遇到诡异的崩溃问题
-(void)test_group_03{
dispatch_group_t group = dispatch_group_create();//create
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(group);//enter
dispatch_group_async(group, queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-01:%@",[NSThread currentThread]);
});
dispatch_group_leave(group);//leave
dispatch_group_enter(group);//enter
dispatch_group_async(group, queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-02:%@",[NSThread currentThread]);
});
dispatch_group_leave(group);//leave
dispatch_group_enter(group);//enter
dispatch_group_async(group, queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-03:%@",[NSThread currentThread]);
});
dispatch_group_leave(group);//leave
NSLog(@"flag.....");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任务完成");
});
}
// 打印
flag.....
task-01:<NSThread: 0x60000067b080>{number = 5, name = (null)}
task-03:<NSThread: 0x600000635100>{number = 3, name = (null)}
task-02:<NSThread: 0x600000670480>{number = 4, name = (null)}
任务完成
dispatch_apply
dispatch_apply表现得就像一个 for 循环,但它能并发地执行不同的迭代。这个函数是同步的,所以和普通的 for 循环一样,它只会在所有工作都完成后才会返回。
当在 Block 内计算任何给定数量的工作的最佳迭代数量时,必须要小心,因为过多的迭代和每个迭代只有少量的工作会导致大量开销以致它能抵消任何因并发带来的收益。而被称为跨越式(striding)的技术可以在此帮到你,即通过在每个迭代里多做几个不同的工作
那何时才适合用 dispatch_apply 呢?
- 自定义串行队列:串行队列会完全抵消 dispatch_apply 的功能;你还不如直接使用普通的 for 循环。
- 主队列(串行):与上面一样,在串行队列上不适合使用 dispatch_apply 。还是用普通的 for 循环吧。
- 并发队列:对于并发循环来说是很好选择,特别是当你需要追踪任务的进度时
- (void)test_apply{
dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) {
sleep(arc4random()%10*0.5);
NSLog(@"task-%ld:%@",i,[NSThread currentThread]);
});
NSLog(@"flag....");
}
// 打印
task-3:<NSThread: 0x600002d45000>{number = 6, name = (null)}
task-2:<NSThread: 0x600002d6e540>{number = 3, name = (null)}
task-4:<NSThread: 0x600002d78180>{number = 5, name = (null)}
task-1:<NSThread: 0x600002d70480>{number = 4, name = (null)}
task-0:<NSThread: 0x600002d24f00>{number = 1, name = main}
flag....
dispatch apply 是同步的,可以在主线程走任务,如果想异步可以在外面包一层
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) {
sleep(arc4random()%10*0.5);
NSLog(@"task-%ld:%@",i,[NSThread currentThread]);
});
});
NSLog(@"flag....");
打印:
flag....
task-4:<NSThread: 0x600002bb02c0>{number = 6, name = (null)}
task-3:<NSThread: 0x600002ba4000>{number = 8, name = (null)}
task-1:<NSThread: 0x600002bbab00>{number = 7, name = (null)}
task-2:<NSThread: 0x600002ba5280>{number = 9, name = (null)}
task-0:<NSThread: 0x600002ba1300>{number = 10, name = (null)}
dispatch_barrier_async
方法会等待前面追加到并发队列中的任务全部执行完毕之后,再将自己指定的任务追加到该异步队列中,任务执行完毕之后,异步队列才恢复为一般动作,接着追加后面任务到该异步队列并开始执行
-(void)test_barrier{
dispatch_queue_t queue = dispatch_queue_create("queue_name", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-01:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-02:%@",[NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-barrier:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-03:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(arc4random()%10*0.5);
NSLog(@"task-04:%@",[NSThread currentThread]);
});
}
打印:
task-01:<NSThread: 0x6000006ee7c0>{number = 5, name = (null)}
task-02:<NSThread: 0x6000006e9e40>{number = 4, name = (null)}
task-barrier:<NSThread: 0x6000006e9e40>{number = 4, name = (null)}
task-04:<NSThread: 0x6000006ee7c0>{number = 5, name = (null)}
task-03:<NSThread: 0x6000006e9e40>{number = 4, name = (null)}