主要涉及到的概念git
知识点:程序员
任务的执行方式有两种,队列有四种,共有8种组合,分别为:github
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueSerial, task);
dispatch_sync(queueSerial, task1);
NSLog(@"end");
复制代码
当前是在主线程运行,同步执行会阻塞当前线程(主线程),因此end会在执行完task
和task1
以后输出,安全
dispatch_sync(queueSerial, task);
复制代码
dispatch_sync
阻塞当前线程(主线程)queueSerial
中插入任务task
task
任务task
任务执行完成解除对当前线程(主线程)的阻塞dispatch_sync(queueSerial, task1); //同理
复制代码
dispatch_sync
阻塞当前线程(主线程)queueSerial
中插入任务task1
task1
任务task1
任务执行完成解除对当前线程(主线程)的阻塞因此执行顺序为task
->task1
->end
markdown
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueConcurrent, task);
dispatch_sync(queueConcurrent, task1);
NSLog(@"end");
复制代码
在当前线程同步执行不管是串行队列仍是并发队列任务都是按照顺序执行,其结果和 同步执行+串行队列 一致多线程
//第一个参数是队列优先级,第二个参数是保留值默认传0
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueGlobal, task);
dispatch_sync(queueGlobal, task1);
NSLog(@"end");
复制代码
全局队列本质是并发队列,其结果和 同步执行+并发队列 一致并发
dispatch_queue_t queueMain = dispatch_get_main_queue();
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueMain, task); //我也是一个任务 记为 sync1
dispatch_sync(queueMain, task1);
NSLog(@"end");
复制代码
这种状况比较特殊,会引发死锁,其缘由是同步执行语句dispatch_sync(queueMain, task);
自己也是一个任务,咱们记为 sync1
,sync1
任务是在当前线程(主线程)同步执行的,sync1
任务是向主队列中添加一个任务task
并在当前线程(主线程)同步执行任务task
,也就是说sync1
任务执行完成的前提是task
任务执行完成。 由于task
任务是在sync1
任务以后插入主队列的,因此主线程要先执行完sync1
任务才会去执行task
任务,而sync1
任务执行完成的前提是task
任务执行完成,因此就陷入了死锁状态,形成崩溃。app
相似的异步
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task1)(void) = ^{
NSLog(@"死锁了吗");
};
void(^task2)(void) = ^{
dispatch_sync(queueSerial, task1);
};
//开辟子线程,并向串行队列queueSerial中添加任务 task2
dispatch_async(queueSerial, task2);
复制代码
dispatch_async(queueSerial, task2);
自己也是一个任务记为sync1
,但不一样的是sync1
是在当前线程(主线程)执行,sync1
任务执行结果是向串行队列queueSerial
中添加任务task2
并开辟子线程执行task2
,任务task2
是向串行队列queueSerial
中添加任务task1
并在当前线程同步执行任务task1
,也就是说task2
任务执行完成的前提是task1
任务执行完成,由于task2
任务比task1
任务先添加到串行队列queueSerial
,因此任务task2
执行完成以后才会去执行tasi1
,async
注意:异步执行+串行队列只会开辟一条子线程
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueSerial, task); //我也是一个任务 记为 sync1
dispatch_async(queueSerial, task1);
NSLog(@"end");
复制代码
将task
和task1
分别添加到串行队列queueSerial
,开辟一条子线程顺序执行队列queueSerial
中的任务,由于end是在主线程输出的,因此输出顺序为end
->task
->task1
,由于异步执行+串行队列只开辟一条子线程,因此task
和task1
在同一个线程中执行
这个时候理论上能够开辟多个子线程了
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueConcurrent, task);
dispatch_async(queueConcurrent, task1);
NSLog(@"end");
复制代码
由于task
和task1
有可能不是在同一个字线程执行的,两个任务不必定谁先结束执行,因此不能肯定task
和task1
谁先输出,由于end是在主线程输出的,因此先输出end
dispatch_queue_t queueMain = dispatch_get_main_queue();
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueMain, task);
dispatch_async(queueMain, task1);
复制代码
主队列本质上也是一个串行队列,因此按照顺序执行task
->task1
,另外祝队列任务只能在主线程执行,因此task
和task1
都在主线程执行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueGlobal, task);
dispatch_async(queueGlobal, task1);
复制代码
全局队列是一个并发队列,因此有能力开辟多个子线程,固然也可能在一个子线程中去执行
咱们须要将一些耗时任务放在子线程,执行完毕以后再回到主线程刷新页面
dispatch_queue_t queueMain = dispatch_get_main_queue();
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_async(queueGlobal, ^{
sleep(3);//模拟耗时操做
dispatch_async(queueMain, ^{
NSLog(@"主线程");
});
});
复制代码
在《程序员的自我修养:连接、装载与库。》一书的过分优化部分有这么一段话
“CPU的乱序执行能力让咱们对多线程的安全保障的努力变得异常困难。所以要保证线程安全,阻止CPU换序是必需的。遗憾的是,如今并不存在可移植的阻止换序的方法。一般状况下是调用CPU提供的一条指令,这条指令经常被称为barrier。一条barrier指令会阻止CPU将该指令以前的指令交换到barrier以后,反之亦然。换句话说,barrier指令的做用相似于一个拦水坝,阻止换序“穿透”这个大坝。”
摘录来自: 俞甲子 石凡 潘爱民. “程序员的自我修养:连接、装载与库。” Apple Books.
为了保证某些操做的原子性,CUP提供了barrier
指令,用来保证在barrier
指令以前的指令执行完成以后才会执行barrier
以后的指令,dispatch_barrier_async
的意思大致也是如此,在异步执行并发队列中保证先执行完dispatch_barrier_async
以前的任务,而后再执行dispatch_barrier_async
中的任务,其次执行dispatch_barrier_async
以后的任务
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_async(queueGlobal, ^{
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
sleep(2);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_async(queueGlobal, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
复制代码
全局队列是一个并发队列,盲猜这里应该先打印出来1
和2
,而后执行barrier
,而后随机打出3
和4
,可是实际上呢
barrier
彷佛跟dispatch_async
同样,并无起到什么做用,查了一番资料终于在官方文档找到正解 dispatch_barrier_async
若是本身经过dispatch_queue_create
建立并发队列没问题,若是是一个串行队列或者全局并发队列那么和dispatch_async
效果同样同样的,咱们换成本身建立的并发队列
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queueConcurrent, ^{
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_async(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
NSLog(@"end");
复制代码
从结果看到dispatch_barrier_async
并无阻塞当前线程,而只是阻塞了当前异步队列其余任务的执行,官方文档也证明了这一点
咱们先去官方文档看一下dispatch_barrier_sync
一方面dispatch_barrier_sync
会阻塞当前线程,另外一方面可能形成死锁deadlock
,咱们验证一下
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_sync(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
NSLog(@"end");
复制代码
咱们看到dispatch_barrier_sync
确实阻塞了当前线程,end
是在dispatch_barrier_sync
以后输出的
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_barrier_sync(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
dispatch_sync(queueConcurrent, ^{
NSLog(@"%@",[NSThread currentThread]);
});
});
复制代码
不知道这是否是文档中所说的Calling this function and targeting the current queue results in deadlock.
反正实现了deadlock
效果
另外文档提到了Block_copy
我从源码看到确实dispatch_barrier_async
调用了_dispatch_Block_copy
而dispatch_barrier_sync
是没有copy,这多是由于dispatch_barrier_sync
阻塞线程后面代码不执行,而dispatch_barrier_async
没有阻塞线程,那么后面就可能对函数体修改????因此拷贝一份这里留下问好
2秒以后将任务添加到主队列,具体何时执行还要看CUP的调度
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), mainQueue, ^{
//2秒以后将任务添加到主队列,具体何时执行还要看CUP的调度
NSLog(@"执行了");
});
复制代码
实现单例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//单例
});
复制代码
更多内容能够看一下# iOS多线程之dispatch_once剖析
先来看一下文档dispatch_apply
能够看到dispatch_apply
和可重入且安全的并发队列能够实现高效的遍历操做,若是是一个串行队列那么就体现不出来他的高效之处了
dispatch_apply(10, queueGlobal, ^(size_t index) {
NSLog(@"%zd--%@",index,[NSThread currentThread]);
});
NSLog(@"end");
复制代码
dispatch_apply
会利用多个线程来遍历,不光是子线程,还能够调用主线程,另外他还会阻塞当前线程
dispatch_group
做为一个单元监控一组任务。你能够将一组任务放到一个组里经过dispatch_group
同步他们的行为。你能够将这些任务放在组里之后在同一个队列或者不一样的队列异步执行,能够在不阻塞当前线程的状况下监听这些异步任务执行完毕,也能够阻塞当前线程等待这些任务完成。
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_notify(group, queueGlobal, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
dispatch_group_notify
并无阻塞当前线程,他是在当前组的其余队列都执行完成以后再执行,咱们能够将dispatch_group_notify
任务放在主队列执行,这就实现了回调主线程的功能
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queueMain = dispatch_get_main_queue();
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueSerial, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueSerial, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_notify(group, queueMain, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
阻塞当前线程,等待组内任务都执行完成才会继续执行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
直到前面三个任务都执行完成才会打印end,固然也能够将阻塞的超时时间设置小一些,即便前面任务没有完成,可是时间到了也会继续执行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(3);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)));
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
dispatch_group_async
内部也是经过dispatch_group_enter
和dispatch_group_leave
来实现的
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
sleep(3);
NSLog(@"1--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_notify(group, queueGlobal, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
实现了和dispatch_group_async
同样的效果
在开发中常常须要线程同步,那么信号量是一个很好的选择,dispatch_semaphore_signal
信号量+1,dispatch_semaphore_wait
信号量-1,若是信号量小于0那么阻塞当前线程,能够设置阻塞的超时时间
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queueGlobal, ^{
sleep(3);//耗时操做
NSLog(@"1--%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//信号量+1
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信号量-1
dispatch_async(queueMain, ^{
NSLog(@"主线程");
});
NSLog(@"end--%@",[NSThread currentThread]);
复制代码
多线程访问同一个数据有可能形成数据不安全,例如
__block int i = 5;
while (i>0) {
dispatch_async(queueGlobal, ^{
i--;
NSLog(@"%d--%@",i,[NSThread currentThread]);
});
}
复制代码
因为多线程同时修改i
致使结果和预期出现了很大的出入,甚至NSLog
函数的打印都出问题了😂,经过信号量能够解决这个问题
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int i = 5;
while (i>0) {
dispatch_async(queueGlobal, ^{
i--;
NSLog(@"%d--%@",i,[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
复制代码
这个时候咱们看到结果按照预期输出了,由于信号量控制最多只有一个线程能够访问变量i
(不必定是同一个线程,但同一时间最多只能有一个线程访问)
dispatch_set_target_queue
有两个做用一是改变队列优先级,二是让多个串行队列之间也能串行地执行任务。
咱们前边所学的方法都是控制队列内部的任务的操做顺序,可是不一样队列之间是没有依赖关系的,假如咱们把A任务放在自定义串行队列serialQueueA中,把B任务放在自定义并发队列conQueueB中,那么咱们不知道任务A和任务B的前后执行顺序,有了dispatch_set_target_queue
咱们能够利用其改变队列优先级的做用实现优先队列
dispatch_queue_create
建立的队列,不管是串行仍是并发,其优先级都是 DISPATCH_QUEUE_PRIORITY_DEFAULT
,使用 dispatch_set_target_queue
能够改变队列优先级,注意改变的是优先调度开始顺序,而不是结束顺序,先被调度的不必定先结束执行
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
复制代码
这个时候咱们不能肯定ABCDEFGH谁先执行,简单修改一下
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
复制代码
咱们增长了两行代码
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
复制代码
网上看了好多例子都是到此为止,以致于我任务只是由于我给globalQueueLow
设置的优先级为DISPATCH_QUEUE_PRIORITY_BACKGROUND
因此serialQueue2
的优先级才笔另外几个串行队列低,若是我设置优先级为DISPATCH_QUEUE_PRIORITY_HIGH
那么队列就会优先调度
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_queue_t globalQueueHight = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
dispatch_set_target_queue(serialQueue3, globalQueueHight);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
复制代码
多运行几回咱们发现设置DISPATCH_QUEUE_PRIORITY_HIGH
优先级以后串行队列serialQueue3
并无比其余优先级高,而仅仅比serialQueue2
高了而已,咱们前边也说过,这种优先级高仅仅是开始调度的优先级高,而不是结束调度的优先级,若是咱们给任务A设置一个耗时任务就能够验证
dispatch_async(serialQueue1, ^{
int a=0;
for (int i=0; i<1000000; i++) {
a++;
}
NSLog(@"%d-taskA",a);
});
复制代码
这时A并无先结束执行,BC也没有最后结束执行
若是咱们设置
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_set_target_queue(serialQueue3, mainQueue);
复制代码
这个时候是否是serialQueue3
的优先级会不会很高呢,其实并无
看了官方文档也是很难理解dispatch_set_target_queue,我我的理解是若是经过dispatch_set_target_queue
设置队列优先级的这些队列他们都成了二级公民,依赖于同一个队列的子队列之间能够经过优先级来设置,可是他们的优先级都要比没有设置过优先级的队列优先级要低了
咱们可使用dispatch_set_target_queue
+dispatch_suspend/dispatch_resume
实现一个优先队列
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(serialQueue1, serialQueue2);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_suspend(serialQueue1);
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
dispatch_resume(serialQueue1);
});
dispatch_async(serialQueue1, ^{
NSLog(@"taskC");
});
复制代码