服务报价 | 域名主机 | 网络营销 | 软件工具| [加入收藏]
当前位置: 主页 > 开发教程 > ios开发教程 >

iOS-GCD中disPatch队列和线程的关系

时间:2016-02-07 01:10来源:未知 作者:好模板 点击:
关于GCD的最最基本的知识,往往很多初学者都被忽略。理解上造成了偏差,而不注重去实践, 所有我们需要认真的总结一下。 dispatch_asyn和dispatch_sync添加任务到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
(责任编辑:好模板)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------