串行(Serial)
任务只能一个个按顺序执行,只能等到上一个任务执行完毕,才能执行当前的任务;
并发 (Concurrent):
任务不按顺序执行,不用等待上一个任务执行完,多个任务是同时执行的;在异步情况下可开启多个线程执行任务;
同步(Synchronous):
- 不具备开启新线程的能力;
- 任务执行完才返回;
- 同步函数: dispatch_sync();
异步 (Asynchronous):
- 具备开启新线程的能力;
- 提交的任务立即返回;
- 异步函数: dispatch_async();
队列 (Dispatch Queue)
苹果为我们提供了串行队列,并行队列,全局队列,主队列!
- 串行队列
dispatch_queue_t queue = dispatch_queue_create("com.mjz.cn", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
dispatch_queue_t queue = dispatch_queue_create(0, 0);
- 并行队列
dispatch_queue_t queue = dispatch_queue_create("com.mjz.cn", DISPATCH_QUEUE_CONCURRENT);
- 全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
- 主队列
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync
- 串行队列同步执行
dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
for (NSInteger index=0; index<20; index++) {
dispatch_sync(queue, ^{
NSLog(@"%ld<-->%@-->%f", index, [NSThread currentThread], [NSThread currentThread].threadPriority);
});
}
- queue是串行队列;
- dispatch_sync是同步执行,不会开启新的线程;
结论:任务按顺序执行,下一个任务只有等待上个任务执行完才能执行!
- 并行队列同步执行
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
for (NSInteger index=0; index<20; index++) {
dispatch_sync(queue, ^{
NSLog(@"%ld<-->%@-->%f", index, [NSThread currentThread], [NSThread currentThread].threadPriority);
});
}
- queue是并行队列;
- dispatch_sync是同步执行,不会开启新的线程;
结论:虽然是并行队列,但是dispatch_sync不会开启线程,所以任务还是按顺序执行,跟上面一样的结果!
dispatch_async
- 串行队列异步执行
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
for (NSInteger index=0; index<20; index++) {
dispatch_async(queue, ^{
NSLog(@"%ld<-->%@", index, [NSThread currentThread]);
});
}
- queue是串行队列;
- dispatch_sync是异步执行,开启新的线程;
结论:串行队列任务按顺序执行,但dispatch_async会开启一个新的线程执行!
- 并行队列异步执行
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
for (NSInteger index=0; index<20; index++) {
dispatch_async(queue, ^{
NSLog(@"%ld<-->%@", index, [NSThread currentThread]);
});
}
- queue是并行队列;
- dispatch_sync是异步执行,开启新的线程;
结论:并行队列任务同时执行,加上dispatch_async会开启新线程,所以此时会生成多个线程同时执行任务!
一张图总结
Dispatch Group
在串行队列情形下,任务都是按顺序逐一执行;但是到了并行队列的状态下,队列要实现某个任务等到其它队列执行完后才执行就有点难了,这时候我们需要引入了Dispatch Group!
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
NSLog(@"11 %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"22 %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"44 %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"55 %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"66 %@", [NSThread currentThread]);
});
NSLog(@"-------------------------------------");
dispatch_group_notify(group, queue, ^{
NSLog(@"33 %@", [NSThread currentThread]);
});
- dispatch_group_notify可以轻松地帮助我们实现保证在dispatch_group_notify前的任务执行完成后,dispatch_group_notify中block的任务才能执行,实在方便!
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"11");
});
dispatch_async(queue, ^{
NSLog(@"22");
});
dispatch_async(queue, ^{
NSLog(@"33");
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"66");
dispatch_group_leave(group);
});
- dispatch_group_enter与dispatch_group_leave实现dispatch_group_notify类似效果!!
Dispatch Block
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"mjz");
});
dispatch_async(queue, block);
- dispatch_block_t将任务定义成block,并用队列实现,是队列实现任务的另一种形式!!
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create(0, ^{
sleep(5.0);
NSLog(@"mjz");
});
dispatch_async(queue, block);
long result = dispatch_block_wait(block, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*5.0));
if (result==0) {
NSLog(@"wait finish!!");
} else {
NSLog(@"wait error!!");
}
- dispatch_block_wait等待block任务执行完毕,会阻塞当前线程,阻塞的时间在wait函数时间值和当前block任务执行时间值取最小的!!
dispatch_queue_t queue = dispatch_queue_create("com.mjz.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"block start");
[NSThread sleepForTimeInterval:1];
NSLog(@"block1 end");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
NSLog(@"block2 finish");
});
dispatch_async(queue, block);
dispatch_async(queue, block2);
dispatch_block_cancel(block2);
- dispatch_block_cancel取消当前队列执行的任务!!!
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(6, queue, ^(size_t i) {
NSLog(@"index: %ld",i);
});
NSLog(@"end!!!");
- dispatch_apply类似一个for循环,会在指定的dispatch queue中运行block任务n次;
- 串行队列则会按顺序执行n次任务;
- 并行队列并发执行n次任务,无序!!
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"11");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"22");
});
dispatch_barrier_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"33");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"44");
});
- dispatch_barrier_async用于等待前面的任务执行完毕后自己才执行,而它后面的任务需等待它完成之后才执行。
其它
- dispatch_queue_create函数的第一个参数指定SERIAL_QUEUE名称,dispatch_queue的名称方便编译器调试;
- dispatch_queue_create创建的一个串行队列将生成一个对应的线程执行任务,若是创建多个则将生成多个线程,存在内存安全隐患;
- 使用GCD避免死锁问题;