iOS-GCD之初,disPatch队列和线程的关系

关于GCD的最最基本的知识,往往很多初学者都被忽略。理解上造成了偏差,而不注重去实践, 所有我们需要认真的总结一下。

dispatch_asyn和dispatch_sync添加任务到dispatch队列时,是否创建线程呢,那么创建线程是创建一个呢还是多个呢,如果你自己能直接分的清楚就不必看我下文的实践代码了, 下文的代码做了详细的说明, 不仅仅是代码,也包含了总结, 如果你想实践的话, 也可以跟着实践一遍哦,这样最好哦

以下主要总结了队列的类型队列的堵塞


- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    //********
    [self blockIntroduced];
    //********通过以上测试我们得出如下几个结论
    
    /*
     1.dispatch_sync添加任务到队列,不会创建新的线程都是在当前线程中处理的。无论添加到串行队列里或者并行队列里,都是串行效果,因为这个方法是等任务执行完成以后才会返回。
     2.dispatch_async添加任务到
       2-1:mainQueue不创建线程,在主线程中串行执行
       2-2:globalQueue 和 并行队列:根据任务系统决定开辟线程个数
       2-3:串行对列:创建一个线程:串行执行。
     
    */
    
    
    [self blockedMainThread0];
    [self blockedMainThread1];
    [self blockedMainThread2];
    [self blockedMainThread3];
//    [self blockedMainThread];
    
}

-(void)blockIntroduced
{
    //队列一般就是系统的主队列和全局队列还有自己手动创建的串行队列和并行队列
    dispatch_queue_t chuanxingduilie = dispatch_queue_create("chuanxingduilie", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t bingxingduilie = dispatch_queue_create("bingxingduilie", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    
    //方法有两个  dispatch_sync 和 dispatch_async  dispatch_async方法是立刻返回的,也就是说把block内容加到相应队列里后会立马返回,而dispatch_sync要等到加到队列里执行完之后才会返回。
    //这时候总共有2*4 = 8种组合,接下来我们来说一下这八种组合
    
    
    //一:
    for(int i=0;i<3;i++){
        dispatch_sync(chuanxingduilie, ^{
            NSLog(@"dispatch_sync-chuanxingduilie-%d\n mainThread:%@",i,[NSThread currentThread]);
        });
    }
    /*
     2016-02-05 21:07:12.622 GcdTest[7229:164997] dispatch_sync-chuanxingduilie-0
     mainThread:<NSThread: 0x7fad93407dd0>{number = 1, name = main}
     2016-02-05 21:07:12.623 GcdTest[7229:164997] dispatch_sync-chuanxingduilie-1
     mainThread:<NSThread: 0x7fad93407dd0>{number = 1, name = main}
     2016-02-05 21:07:12.623 GcdTest[7229:164997] dispatch_sync-chuanxingduilie-2
     mainThread:<NSThread: 0x7fad93407dd0>{number = 1, name = main}

     */
    //第一种方式可见,串行队列是在主线程里完成的,因为是串行队列,所以打印%d是有顺序的。
    
    //二:
    for(int i=0;i<3;i++){
        dispatch_sync(bingxingduilie, ^{
            
            NSLog(@"dispatch_sync-bingxingduilie-%d\n mainThread:%@",i,[NSThread currentThread]);
    
        });
    }
    /*
     2016-02-05 21:09:26.422 GcdTest[7241:165846] dispatch_sync-bingxingduilie-0
     mainThread:<NSThread: 0x7face9d01d20>{number = 1, name = main}
     2016-02-05 21:09:26.422 GcdTest[7241:165846] dispatch_sync-bingxingduilie-1
     mainThread:<NSThread: 0x7face9d01d20>{number = 1, name = main}
     2016-02-05 21:09:26.422 GcdTest[7241:165846] dispatch_sync-bingxingduilie-2
     mainThread:<NSThread: 0x7face9d01d20>{number = 1, name = main}

    */
    //第二种方式可以发现同样还是在主线程里执行并行队列,(虽然是并行队列,但这时候依然在同一个线程里执行)
    
    //三:
    /*
    for(int i=0;i<3;i++){
        NSLog(@"dispatch_sync-mainQueue");
        dispatch_sync(mainQueue, ^{
            
            NSLog(@"dispatch_sync-mainQueue-%d\n mainThread:%@",i,[NSThread currentThread]);
            
        });
    }
    //打印结果:dispatch_sync-mainQueue,发现主线程被堵塞。原因在堵塞中分析。此种方式暂时先屏蔽掉
    */
    
    //四:
    for(int i=0;i<3;i++){
        dispatch_sync(globalQueue, ^{
            
            NSLog(@"dispatch_sync-globalQueue-%d\n mainThread:%@",i,[NSThread currentThread]);
            
        });
    }
    /*
     2016-02-05 21:22:41.107 GcdTest[7338:172870] dispatch_sync-globalQueue-0
     mainThread:<NSThread: 0x7feadad050b0>{number = 1, name = main}
     2016-02-05 21:22:41.107 GcdTest[7338:172870] dispatch_sync-globalQueue-1
     mainThread:<NSThread: 0x7feadad050b0>{number = 1, name = main}
     2016-02-05 21:22:41.107 GcdTest[7338:172870] dispatch_sync-globalQueue-2
     mainThread:<NSThread: 0x7feadad050b0>{number = 1, name = main}
     */
    //打印结果可以看出依然是主线程。
    
    //五:
    for (int i=0; i<3; i++) {
        dispatch_async(chuanxingduilie, ^{
            if (i==1) {
                sleep(2);
            }
            NSLog(@"dispatch_async-chuanxingduilie-%d\n Thread:%@",i,[NSThread currentThread]);
        });
    }
    /*
     2016-02-05 22:32:14.957 GcdTest[7499:191789] dispatch_async-chuanxingduilie-0
     Thread:<NSThread: 0x7fd7eaf10c70>{number = 3, name = (null)}
     2016-02-05 22:32:16.962 GcdTest[7499:191789] dispatch_async-chuanxingduilie-1
     Thread:<NSThread: 0x7fd7eaf10c70>{number = 3, name = (null)}
     2016-02-05 22:32:16.963 GcdTest[7499:191789] dispatch_async-chuanxingduilie-2
     Thread:<NSThread: 0x7fd7eaf10c70>{number = 3, name = (null)}
     */
    //可以看出创建了一个线程, 在串行队列里串行执行的
    
    
    //六:
    for (int i=0; i<3; i++) {
        dispatch_async(bingxingduilie, ^{
            if (i==1) {
                sleep(3);
            }
            NSLog(@"dispatch_async-bingxingduilie-%d\n Thread:%@",i,[NSThread currentThread]);
        });
    }
    /*
     2016-02-05 22:10:07.083 GcdTest[7425:184003] dispatch_async-bingxingduilie-2
     Thread:<NSThread: 0x7fcda24bcd00>{number = 4, name = (null)}
     2016-02-05 22:10:07.083 GcdTest[7425:183982] dispatch_async-bingxingduilie-0
     Thread:<NSThread: 0x7fcda2502310>{number = 3, name = (null)}
     2016-02-05 22:10:10.083 GcdTest[7425:184002] dispatch_async-bingxingduilie-1
     Thread:<NSThread: 0x7fcda2436180>{number = 5, name = (null)}
     */
    //分析可以看出创建了多个线程,任务执行顺序不一定(时间差不多的话)
    
    
    //七:
    for (int i=0; i<3; i++) {
        dispatch_async(mainQueue, ^{
            if (i==1) {
                sleep(3);
            }
            NSLog(@"dispatch_async-mainQueue-%d\n Thread:%@",i,[NSThread currentThread]);
        });
    }
    /*
     Thread:<NSThread: 0x7fbb28704510>{number = 5, name = (null)}
     2016-02-05 22:15:03.709 GcdTest[7460:186485] dispatch_async-mainQueue-0
     Thread:<NSThread: 0x7fbb28703fb0>{number = 1, name = main}
     2016-02-05 22:15:06.710 GcdTest[7460:186485] dispatch_async-mainQueue-1
     Thread:<NSThread: 0x7fbb28703fb0>{number = 1, name = main}
     2016-02-05 22:15:06.710 GcdTest[7460:186485] dispatch_async-mainQueue-2
     Thread:<NSThread: 0x7fbb28703fb0>{number = 1, name = main}
     */
    
    //可以看出这种情况还是在当前线程环境中执行,并不创建线程,因为是在主队列里,顺序执行
    
    //八:
    for (int i=0; i<3; i++) {
        dispatch_async(globalQueue, ^{
        
            NSLog(@"dispatch_async-globalQueue-%d\n Thread:%@",i,[NSThread currentThread]);
        });
    }
    /*
     2016-02-05 22:17:58.306 GcdTest[7482:188067] dispatch_async-globalQueue-1
     Thread:<NSThread: 0x7fa281e24580>{number = 4, name = (null)}
     2016-02-05 22:17:58.306 GcdTest[7482:188099] dispatch_async-globalQueue-2
     Thread:<NSThread: 0x7fa281e321c0>{number = 5, name = (null)}
     2016-02-05 22:17:58.307 GcdTest[7482:188069] dispatch_async-globalQueue-0
     Thread:<NSThread: 0x7fa281e262b0>{number = 3, name = (null)}
     */
   //可以看出创建了多个线程,执行顺序并不一定

}

-(void)blockedMainThread
{
  //打印结果是1  分析:mainQueue里存在任务1,同步线程任务,这两个任务,当执行dispatch_sync时,把打印任务2加入主队列,想要打印2必须等之前所有的任务都执行完成,这时候因为主队列里有同步线程任务,这时候相当于自己在等自己执行完成,进入死循环。
    NSLog(@"1"); // 任务1
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2"); // 任务2
    });
    NSLog(@"3"); // 任务3

}

-(void)blockedMainThread0
{
    //打印结果123  分析:mainQueue里存在任务1,同步线程任务,当执行dispatch_sync时,拿到全局队列,
    NSLog(@"1"); // 任务1
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"2"); // 任务2
    });
    NSLog(@"3"); // 任务3
}

-(void)blockedMainThread1
{
    /*
    //执行结果:
    2016-02-05 22:42:30.661 GcdTest[7511:194820] 1
    2016-02-05 22:42:30.662 GcdTest[7511:194820] 5
    2016-02-05 22:42:30.662 GcdTest[7511:194929] 2 <NSThread: 0x7f9ca8709990>{number = 3, name = (null)}
     */
    dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1"); // 任务1
    dispatch_async(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]); // 任务2
        
        dispatch_sync(queue, ^{
            NSLog(@"3"); // 任务3
        });
        NSLog(@"4"); // 任务4
    });
    NSLog(@"5"); // 任务5
}

-(void)blockedMainThread2
{
    //1,5,2,3,4 可以看出在全局队列里拿到住队列同步执行是没有问题的。
    NSLog(@"****************");
    NSLog(@"1"); // 任务1
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2"); // 任务2
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"3 %@",[NSThread currentThread]); // 任务3
            //2016-02-05 22:51:00.044 GcdTest[7548:198417] 3 <NSThread: 0x7feb3b701be0>{number = 1, name = main}
        });
        NSLog(@"4"); // 任务4
    });
    NSLog(@"5"); // 任务5

}

-(void)blockedMainThread3
{
    //执行结果:11,44
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"11"); // 任务1
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"22"); // 任务2
        });
        NSLog(@"33"); // 任务3
    });
    NSLog(@"44"); // 任务4
    while (1) {
    }
    NSLog(@"55"); // 任务5
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

文章未完待续:待续内容为dispatch里的大部分常用的方法,等我有时间了一定会更新上去, 如果大家喜欢文章, 就关注哦~
有什么不明白的,可以直接评论回复,交流。

1.dispath_once

dispatch_once的作用就是只执行一次,我们在写单例的时候可以用到

+ (BWStatusBarOverlay *)shared {
    static dispatch_once_t pred = 0;
    __strong static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init];
    });
    return _sharedObject;
}

2.dispatch_after

//延迟0.5s以后执行
   dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*0.5);
    dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"doSomething");
    });

3.dispatch_group


    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, globalQueue, ^{
         sleep(1);
        NSLog(@"1");
    });
    dispatch_group_async(group, globalQueue, ^{
        sleep(2);
        NSLog(@"2");
    });
    dispatch_group_async(group, globalQueue, ^{
        sleep(3);
        NSLog(@"3");
    });
    dispatch_group_notify(group, globalQueue, ^{
        NSLog(@"Over!");
    });

4.dispatch_barrier_async


    dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-1");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-2");
    });
    dispatch_barrier_async(concurrentQueue, ^(){
        NSLog(@"dispatch-barrier-1+2");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-3");
    });
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"dispatch-barrier-1+2+3");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-4");
    });

最后不多说,需要看看苹果官方文档这里截图看下关于GCD的东西

gcd-1.png
gcd-2.png
gcd-3.png

看官方的东西其实不会的东西太多太多,任重而道远, 明天就回家过年喽, 祝愿每一个人新的一年都能对自己的目标更近一步。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容