GCD中的“c 全局队列列”和“主队列”有什么区别

dispatch_queue_t serialQueue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
// NSLog(@"1");
NSLog(@"1");
dispatch_sync(serialQueue, ^{
NSLog(@"2");
dispatch_async(serialQueue, ^{
NSLog(@"3");
dispatch_sync(serialQueue, ^{
NSLog(@"4");
dispatch_async(serialQueue, ^{
NSLog(@"5");
看看上面的代码,你猜猜会输出什么东东? &反正在今天之前我会认为它输出坑定不是有序的,之前一直认为串行就是一个一个执行,好,第一个是异步,那就异步去吧,第二个同步,同步执行完,去执行第三个,然后..... &同步就执行完,然后执行下一个,异步就不知道什么时候执行完了。
哈哈哈哈,今天我不得不对自己的想法勘称sb。太自以为是了。从中就可以看出我不能理解串行队列的本质。
那么什么是串行队列?什么是并行队列?
&tasks are dequeued in FIFO order, but run concurrently and can finish in any order.
&tasks execute one at a time in FIFO order
并发: 任务以FIFO从序列中移除,然后并发运行,可以按照任何顺序完成。它会自动开启多个线程同时执行任务
串行: &任务以FIFO从序列中一个一个执行。一次只调度一个任务,队列中的任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)而且只会开启一条线程
为了再次证实串行队列中只有一个线程执行任务:
dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i& 10;i++){
// 10个异步
dispatch_async(queue, ^{
NSLog(@"%@--%d",[NSThread currentThread], i);
我们可以发现thread的地址是一样的,那就证实了serial queue只有一个线程执行任务。然后我们测试一下并发队列
dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i& 10;i++){
// 10个异步
dispatch_async(queue, ^{
NSLog(@"%@--%d",[NSThread currentThread], i);
由上图可以看出并发队列中是有多个线程执行任务的。
比较上面两个程序,我们仅仅是创建了两个不同类型的queue,但是结果迥然不同,并发会开启多个线程,执行的顺序我们无法控制,至于那个线程执行那个任务由队列决定,哪个任务先完成由CPU和操作系统决定,并且并发队列中的线程是可以重复利用(线程池),这也是可以理解的,但是下面:
dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i& 10;i++){
// 10个异步
dispatch_sync(queue, ^{
NSLog(@"%@--%d",[NSThread currentThread], i);
发现并发只能在异步函数下有效,name=main ,还不会创建新线程。所有的任务依次在主线程上执行。
阅读(...) 评论()个回答天前主队列确实在主线程上运行。全局队列是并发队列,来自主页面进行调度。
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW因此,它们是在后台线程上运行的队列,当它们可用时。它们是“非FIFO”,所以顺序不能保证。天前这5个队列:
-main- : 0.758065
DISPATCH_QUEUE_PRIORITY_HIGH : 0.532258
DISPATCH_QUEUE_PRIORITY_DEFAULT : 0.500000
DISPATCH_QUEUE_PRIORITY_LOW : 0.467742
DISPATCH_QUEUE_PRIORITY_BACKGROUND : 0.000000同步,异步,串行队列,并发队列,全局队列,主队列等概念的总结
在GCD函数中, 我们常常碰到同步,异步,串行队列,并发队列,全局队列,主队列等概念,而这些概念又常常组合在一起, 十分头疼, 这篇文章就来梳理一下这些烦人的概念.
不想看长篇大论的, 直接看文章末尾的表格即可!
在此之前, GCD中还涉及到两个十分重要的概念, 就是任务和队列
任务(Task): 你需要执行的操作
队列(Queue): 存放任务的容器
GCD中两个重要的函数, 一个同步执行, 一个异步执行
dispatch_async(dispatch_queue_t& _Nonnull queue, ^(void)block)
dispatch_sync(dispatch_queue_t& _Nonnull queue, ^(void)block)
这个函数中需要填入两个参数, 一个是队列, 一个是任务, 任务就是封装在block代码块中的. 所以, 我们在使用以上两个函数时, 只需要创建队列, 以及把自己需要执行的代码封装在block中就可以了
CGD中还给我们提供了两个类似的函数, 请看
dispatch_sync_f(dispatch_queue_t queue,
&&& void *_Nullable context,
&&& dispatch_function_t work);
dispatch_async_f(dispatch_queue_t queue,
&&& void *_Nullable context,
&&& dispatch_function_t work);
这两个函数就没有之前那两个简单, 因为这两个函数不是将任务封装在block代码块中, 而是封装在函数里
如下面的代码所示
- (void)touchesBegan:(NSSet&UITouch *& *)touches withEvent:(UIEvent *)event {
&&& dispatch_async_f(dispatch_get_global_queue(0, 0), nil, task);
void task (void *param) {
&&& NSLog(@"downloadTask-------%@",[NSThread currentThread]);
dispatch_async_f(_, _, _);这个函数的三个参数我分别传入
一个全局并发队列
参数我传空
定义一个返回值为空, 参数为void*类型的函数, 然后把函数名作为参数传进去
在我定义的这个返回值为空, 参数为void*类型的函数中, 我把我需要操作的任务封装在里面, 其实里面的代码就跟之前block代码块里的代码一模一样. 也能起到同样的效果
那么, 同步执行和异步执行有什么区别呢? 我们先来看看官方文档的解释
When a work item is executed&synchronously&with the&sync&method, the program waits until execution finishes before the method call returns
When a work item is executed&asynchronously&with the&async&method, the method call returns immediately
假如我有A,B,C三个任务,
如果这三个任务都是同步执行, 程序将等待A 执行完毕之后, 再执行B, 再执行C
如果这三个任务都是是异步执行, 程序直接跳过A,B,C,执行后面的代码, 执行完毕之后, 再来执行A,B,C中的任务
另外, 还有一点需要明确的是
同步执行没有开启新线程的能力, 所有的任务都只能在当前线程执行
异步执行有开启新线程的能力, 但是, 有开启新线程的能力, 也不一定会利用这种能力, 也就是说, 异步执行是否开启新线程, 需要具体问题具体分析
我们再来看一下串行队列和并发队列
无论任何队列, 其实都遵循FIFO(first in first out, 先进先出原则),但是:
并发队列中的任务会放到不同的线程中去执行.&
串行队列中的任务只会放到同一线程中去执行.
如下图所示
那么同步执行,异步执行,并发队列,串行队列互相组合又会发生什么样的情况呢? 这个时候, 就有四种情况需要分析了
情况1 : 异步执行 + 并发队列
&&& /****************** -------- 异步执行 + 并发队列 -------- ******************/
- (void)asyncConcurrent {
&&&& /* 1. 创建一个并发队列 */
&&& dispatch_queue_t concurrentQueue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
&&&& /* 2. 将任务放到队列中, 下面的代码将三个任务放到队列中 */
&&& dispatch_async(concurrentQueue, ^{
&&&&&&& NSLog(@"download1-------%@",[NSThread currentThread]);
&&& dispatch_async(concurrentQueue, ^{
&&&&&&& NSLog(@"download2-------%@",[NSThread currentThread]);
&&& dispatch_async(concurrentQueue, ^{
&&&&&&& NSLog(@"download3-------%@",[NSThread currentThread]);
异步执行 + 并发队列 执行情况
可以看出, 开启了不同的线程, 任务完成的顺序也是随机的
但是不同的任务都开启一个独立的线程, 那我有100个任务,会开启100条线程吗? 答案是果断不会, 如下图所示
线程开启数量会无限大吗?
可以看出的是, 任务,10,11,12利用了之前的线程, 所以线程是不会无限开启的.
情况2 : 异步执行 + 串行队列
&&& /****************** -------- 异步执行 + 串行队列 -------- ******************/
- (void)asyncSerial {
&&&& /* 1. 创建一个串行队列 */
&&& dispatch_queue_t serialQueue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL);
&&&& /* 2. 将不同的任务添加到队列中 */
&&& dispatch_async(serialQueue, ^{
&&&&&&& NSLog(@"download1--------%@",[NSThread currentThread]);
&&& dispatch_async(serialQueue, ^{
&&&&&&& NSLog(@"download2--------%@",[NSThread currentThread]);
&&& dispatch_async(serialQueue, ^{
&&&&&&& NSLog(@"download3--------%@",[NSThread currentThread]);
异步执行 + 串行队列 执行情况
可以看出的是: 异步执行 + 串行队列也开启了新的线程, 但是不管任务有多少个, 异步执行 + 同一条串行队列只开启一条新的线程, 任务的执行顺序也是按照队列中的顺序执行的,&因为同一条线程中, 必须等到前一个任务执行完毕后, 才能执行下一个任务.
情况3 : 同步执行+ 并发队列
&&& /****************** -------- 同步执行 + 并发队列 -------- ******************/
- (void)syncConcurrent {
&&&& /* 1. 创建一条并发队列 */
&&& dispatch_queue_t concurrentQueue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
&&&& /* 2. 把任务放到队列中 */
&&& dispatch_sync(concurrentQueue, ^{
&&&&&&& NSLog(@"download1--------%@",[NSThread currentThread]);
&&& dispatch_sync(concurrentQueue, ^{
&&&&&&& NSLog(@"download1--------%@",[NSThread currentThread]);
&&& dispatch_sync(concurrentQueue, ^{
&&&&&&& NSLog(@"download1--------%@",[NSThread currentThread]);
同步执行+ 并发队列 执行情况
三个任务都在主线程中执行, 并没有开启新的线程. 但是, 是不是所有的同步执行的操作都在主线程中执行呢? 当然不是. 看下面的代码
- (void)syncConcurrentOnBackgroundThread {
&&& dispatch_async(dispatch_get_global_queue(0, 0), ^{
&&&&&&& [self syncConcurrent];
我把同步执行+ 并发队列这个操作放到子线程去执行, 那么执行的线程就是子线程
同步执行+ 并发队列 在子线程中执行
所以说, 同步执行+ 并发队列, 并不会开启新的线程, 即使是并发队列, 也然并卵
情况4 : 同步执行+ 串行队列
&&& /****************** -------- 同步操作 + 串行队列 -------- ******************/
- (void)syncSerial {
&&&& /* 1. 创建串行队列 */
&&& dispatch_queue_t serialQueue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL);
&&&& /* 2. 将任务放到队列中 */
&&& dispatch_sync(serialQueue, ^{
&&&&&&& NSLog(@"download1--------%@",[NSThread currentThread]);
&&& dispatch_sync(serialQueue, ^{
&&&&&&& NSLog(@"download2--------%@",[NSThread currentThread]);
&&& dispatch_sync(serialQueue, ^{
&&&&&&& NSLog(@"download3--------%@",[NSThread currentThread]);
同步执行 + 串行队列 执行情况
如果是在子线程中执行同步串行队列的操作, 当前的线程就是子线程
同步执行 + 串行队列 子线程执行情况
总之, 需要记住的就是, 同步执行并没有开启子线程的能力, 所有的操作, 都是在当前线程执行.
故事到这里就结束了吗? 并没有
还有一个操蛋的全局并发队列和主队列, 这两个又是什么鬼呢?
全局并发队列就是我们常说的全局队列
首先, 它是一个并发队列, 他是系统为我们创建好的一个全局的并发队列, 所以, 有时候, 我们不需要自己创建一个并发队列, 直接用系统为我们提供的全局队列就可以了,所以全局队列和同步执行以及异步执行的组合同并发队列是一样的
比较特殊的是主队列系统会把主队列中的任务放在主线程中执行
情况5 : 异步执行+ 主队列
&&& /****************** -------- 异步执行 + 主队列 -------- ******************/
- (void)asyncMainQueue {
&&& dispatch_async(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download1------%@",[NSThread currentThread]);
&&& dispatch_async(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download2------%@",[NSThread currentThread]);
&&& dispatch_async(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download3------%@",[NSThread currentThread]);
异步执行+ 主队列
异步执行虽然有开启新线程的能力, 但是异步执行 + 主队列并不会开启新的线程, 任务都是在主线程中执行的
情况6 : 同步执行+ 主队列
&&& /****************** -------- 同步执行 + 主队列 -------- ******************/
- (void)syncMainQueue {
&&& NSLog(@"------start-------");
&&& dispatch_sync(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download1-------%@",[NSThread currentThread]);
&&& dispatch_sync(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download1-------%@",[NSThread currentThread]);
&&& dispatch_sync(dispatch_get_main_queue(), ^{
&&&&&&& NSLog(@"download1-------%@",[NSThread currentThread]);
&&& NSLog(@"-------end---------");
同步执行+ 主队列 执行情况
直接崩溃了, 以前这种情况是会发生死锁的, 不知道是不是因为是XCode8.2的原因, 现在直接报错. 那么, 为什么会发生这种情况呢?
可以这样理解, 上图中, 执行syncMainQueue这个方法是在主线程中执行的, 你可以把它看做一个任务A, 这个任务A也是在主队列中的,那么代码执行到第179行的时候, 启动了任务B, 把任务B放进了主队列中, 由于是同步执行, 所以, 必须等待任务B执行完了之后才能继续向下执行, 但是主线程有任务A, 所以任务B无法放到主线程中去执行,任务B等待任务A执行, 任务A等待任务B执行, 这样就造成了死锁.
同步执行+ 主队列 造成死锁的原因
但是, 如果将同步执行+ 主队列的操作放到子线程中执行, 就不会造成死锁
同步执行+ 主队列 在子线程中执行情况
那为什么同步执行 + 串行队列不会造成死锁呢?&
同步执行是不会开启新的线程的, 如果当前线程是主线程, 则任务在主线程中执行. 如下图所示
同步执行+ 串行队列 不会造成死锁
说了这么多, 可能又有点晕, 其实这些应该在实际开发中慢慢体会, 碰到的情况多了, 自然而然就明白了. 现在, 我们只要记住下面的表格就可以了
各种队列的执行效果图:
各种队列的执行效果图
原文地址:&
阅读(...) 评论()博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(9311)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'GCD 串行队列和并行队列以及dispatch_group',
blogAbstract:'\n\n\n\n\n\n\n\n并行队列同时会开很多线程,(测试用了11个任务,结果显示11个任务同时执行了),可以使用信号量来控制线程数量,函数concurrentQueueTest中,最多同时运行三个任务;串行队列,执行完一个任务才会执行下一个任务,如果有两个串行队列,则两个串行队列可以并发执行, 见serialQueueTest函数以及其输出;如果某些任务需要更另一些任务完成后才执行,可以使用dispatch_group_t,见groupQueueTest以及其输出;-(void) serialQueueTest',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:9,
publishTime:1,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 python 全局队列 的文章

 

随机推荐