目录
一、定义
1、队列
队列 queue 负责任务的调度,分为串行、并行、主队列,全局队列,队列的调度特点为先进先出,后加入的任务放在队尾。
2、串行并行
串行并行是指队列调度任务的方式,在创建queue时可以看到有两种方式:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
串行队列:一个任务执行完才能执行下一个任务。
并行队列:可以同时执行多个任务。
3、同步异步
同步异步指是否开辟新的线程,dispatch_async 与 dispatch_sync。
同步不会开辟新的线程,任务都是按顺序执行。
异步会开辟新的线程,任务可以同步执行。
二、各种组合
1、同步串行:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@" -- test --1"); // 任务1
});
NSLog(@" -- test --2"); // 任务2
dispatch_sync(queue, ^{
NSLog(@" -- test --3"); // 任务3
});
NSLog(@" -- test --4"); // 任务4
任务依次执行,打印为1,2,3,4
2、异步串行
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@" -- test --1"); // 任务1
});
NSLog(@" -- test --2"); // 任务2
dispatch_async(queue, ^{
NSLog(@" -- test --3"); // 任务3
});
NSLog(@" -- test --4"); // 任务4
因为是异步,所以是可以开辟线程同步执行的,不过因为是异步,所以1,3的顺序是固定的。任务2、4和1、3是的前后顺序是固定的,打印结果为2,1,4,3 或者2,4,1,3等组合。
3、同步并行
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@" -- test --1"); // 任务1
});
NSLog(@" -- test --2"); // 任务2
dispatch_sync(queue, ^{
NSLog(@" -- test --3"); // 任务3
});
NSLog(@" -- test --4"); // 任务4
同步则不开启线程,所以并行没有什么作用,这里和同步串行一样,打印为1,2,3,4.
4、异步并行
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@" -- test --1"); // 任务1
});
NSLog(@" -- test --2"); // 任务2
dispatch_async(queue, ^{
NSLog(@" -- test --3"); // 任务3
});
NSLog(@" -- test --4"); // 任务4
异步并行是经常用到的,同时执行就没有规律了。
三、死锁
1、同步与主线程造成死锁
NSLog(@" -- test 1--");// 任务1
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@" -- test 2--");// 任务2
});
NSLog(@" -- test 3--");// 任务3
打印结果:1,
分析:执行完任务1以后,会来到一个同步线程,该线程做的是将任务2放到主线程队列中打印,但是放到主线程队列只能放到队尾,即任务3后面,所以如果想执行任务2需要先执行任务3,但因为是同步线程,只有执行完任务2才能执行任务3,最终造成死锁。
2、同步与某一线程造成死锁
dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
NSLog(@" -- test 1--");
dispatch_sync(queue, ^{
dispatch_sync(queue, ^{
NSLog(@" -- test 3--");
});
});
与上个例子一样的形式。
3、主线程与循环
NSLog(@" -- test 1--");// 任务1
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@" -- test 2--");// 任务2
});
while (1) {
}
NSLog(@" -- test 3--");// 任务3
结果:1,
分析:因为将任务2放到主线程队列,所以放到死循环后面,主线程在死循环中卡死,所以不会往下执行。