理解GCD中任务和队列执行的原理

我们都知道IOS中常用于处理线程的三种方式:NSThreadNSOperationGCD,而GCD有很好的的优点就是不需要我们来处理runLoop的运行循环,它是一套基于C的并发编程(但是强调一下GCD并不能理解为多线程,因为这个并不是自己来控制线程),我们在使用的时候是不需要管理线程的任何生命周期,系统会自动帮我们管理。在底层是有一个任务队列与线程池的概念,如果任务队列与线程池的认识有点模糊,那可以先百度了解一下。我们先来理解以下几个概念。 

1、同步、异步 

同步:表示在当前线程(注意:不一定就表示主线程)执行任务,不去线程池中拿线程 

异步:表示不在当前线程执行任务,需要去线程池拿线程做处理 

2、串行、并发 

串行:表示所有任务一个接一个的在线程中执行 

并发:表示所有任务可以同时在不同线程上执行 

可能这样粗略讲解一下,还是不够清晰,先我们这样理解一下,同步,异步是用来表示是否需要去线程池中取线程,而串行、并发是用来表示怎么去任务队列中取任务的。 

下面我们组合一下上面两种方式通过代码来依次讲解。 

viewDidLoad依次加载 [self test1]; [self test2]; [self test3]; [self test4];进行测试


1、同步、串行(在当前线程中一个一个的执行任务)

 

- (void)test1 {

    //创建一个串行队列

    dispatch_queue_t queue = dispatch_queue_create("test1", DISPATCH_QUEUE_SERIAL);

    

    NSLog(@"thread start %@",[NSThread currentThread]);

    //同步执行任务

    for (NSInteger i = 0; i < 10; i++) {

        dispatch_sync(queue, ^{

            [NSThread sleepForTimeInterval:0.5];

            NSLog(@"%zd -- %@", i,[NSThread currentThread]);

        });

    }

    

    [NSThread sleepForTimeInterval:1];

    NSLog(@"thread stop %@",[NSThread currentThread]);

 

}

执行结果:

2017-10-24 09:51:11.222 GCDTest[1510:249643] thread start {number = 1, name = main}

2017-10-24 09:51:11.723 GCDTest[1510:249643] 0 -- {number = 1, name = main}

2017-10-24 09:51:12.225 GCDTest[1510:249643] 1 -- {number = 1, name = main}

2017-10-24 09:51:12.725 GCDTest[1510:249643] 2 -- {number = 1, name = main}

2017-10-24 09:51:13.227 GCDTest[1510:249643] 3 -- {number = 1, name = main}

2017-10-24 09:51:13.728 GCDTest[1510:249643] 4 -- {number = 1, name = main}

2017-10-24 09:51:14.229 GCDTest[1510:249643] 5 -- {number = 1, name = main}

2017-10-24 09:51:14.730 GCDTest[1510:249643] 6 -- {number = 1, name = main}

2017-10-24 09:51:15.232 GCDTest[1510:249643] 7 -- {number = 1, name = main}

2017-10-24 09:51:15.733 GCDTest[1510:249643] 8 -- {number = 1, name = main}

2017-10-24 09:51:16.233 GCDTest[1510:249643] 9 -- {number = 1, name = main}

 

2017-10-24 09:51:17.234 GCDTest[1510:249643] thread stop {number = 1, name = main}

从结果可以看出,执行依次从上到下一个一个的执行。


2、异步串行(会去线程池拿线程,但是任务顺序执行)

 

- (void)test2 {

    //创建一个串行队列

    dispatch_queue_t queue = dispatch_queue_create("test2", DISPATCH_QUEUE_SERIAL);

    

    NSLog(@"thread start %@",[NSThread currentThread]);

    //异步执行任务

    for (NSInteger i = 0; i < 10; i++) {

        dispatch_async(queue, ^{

            [NSThread sleepForTimeInterval:0.5];

            NSLog(@"%zd -- %@", i,[NSThread currentThread]);

        });

    }

    

    [NSThread sleepForTimeInterval:1];

    NSLog(@"thread stop %@",[NSThread currentThread]);

 

}

 

执行结果:

2017-10-24 09:53:20.189 GCDTest[1557:268208] thread start {number = 1, name = main}

2017-10-24 09:53:20.691 GCDTest[1557:268552] 0 -- {number = 3, name = (null)}

2017-10-24 09:53:21.190 GCDTest[1557:268208] thread stop {number = 1, name = main}

2017-10-24 09:53:21.195 GCDTest[1557:268552] 1 -- {number = 3, name = (null)}

2017-10-24 09:53:21.698 GCDTest[1557:268552] 2 -- {number = 3, name = (null)}

2017-10-24 09:53:22.203 GCDTest[1557:268552] 3 -- {number = 3, name = (null)}

2017-10-24 09:53:22.709 GCDTest[1557:268552] 4 -- {number = 3, name = (null)}

2017-10-24 09:53:23.215 GCDTest[1557:268552] 5 -- {number = 3, name = (null)}

2017-10-24 09:53:23.721 GCDTest[1557:268552] 6 -- {number = 3, name = (null)}

2017-10-24 09:53:24.221 GCDTest[1557:268552] 7 -- {number = 3, name = (null)}

2017-10-24 09:53:24.722 GCDTest[1557:268552] 8 -- {number = 3, name = (null)}

 

2017-10-24 09:53:25.228 GCDTest[1557:268552] 9 -- {number = 3, name = (null)}

从执行结果看出,thread startthread stop在主线程中执行完成,其他的开辟了一个子线程执行 


3、同步并发(在当前队列执行,可以同时取出多个任务(取出那么多任务,只有一个线程,但是在实际中这种方式几乎没有什么用)

 

- (void)test3 {

    //创建一个并行队列

    dispatch_queue_t queue = dispatch_queue_create("test3", DISPATCH_QUEUE_CONCURRENT);

    

    NSLog(@"thread start %@",[NSThread currentThread]);

    //同步执行任务

    for (NSInteger i = 0; i < 10; i++) {

        dispatch_sync(queue, ^{

            [NSThread sleepForTimeInterval:0.5];

            NSLog(@"%zd -- %@", i,[NSThread currentThread]);

        });

    }

    

    [NSThread sleepForTimeInterval:1];

    NSLog(@"thread stop %@",[NSThread currentThread]);

 

}

执行结果:

2017-10-24 10:00:24.400 GCDTest[1619:296588] thread start {number = 1, name = main}

2017-10-24 10:00:24.901 GCDTest[1619:296588] 0 -- {number = 1, name = main}

2017-10-24 10:00:25.402 GCDTest[1619:296588] 1 -- {number = 1, name = main}

2017-10-24 10:00:25.904 GCDTest[1619:296588] 2 -- {number = 1, name = main}

2017-10-24 10:00:26.405 GCDTest[1619:296588] 3 -- {number = 1, name = main}

2017-10-24 10:00:26.907 GCDTest[1619:296588] 4 -- {number = 1, name = main}

2017-10-24 10:00:27.408 GCDTest[1619:296588] 5 -- {number = 1, name = main}

2017-10-24 10:00:27.910 GCDTest[1619:296588] 6 -- {number = 1, name = main}

2017-10-24 10:00:28.412 GCDTest[1619:296588] 7 -- {number = 1, name = main}

2017-10-24 10:00:28.913 GCDTest[1619:296588] 8 -- {number = 1, name = main}

2017-10-24 10:00:29.414 GCDTest[1619:296588] 9 -- {number = 1, name = main}

 

2017-10-24 10:00:30.416 GCDTest[1619:296588] thread stop {number = 1, name = main}

从执行结果可以看出,所有任务都在主线程中执行,任务依次一个一个执行。


4、并发、异步(拿线程,同时拿任务)这才是多线程的精髓,灵魂

 

- (void)test4 {

    //创建一个并行队列

    dispatch_queue_t queue = dispatch_queue_create("test4", DISPATCH_QUEUE_CONCURRENT);

    

    NSLog(@"thread start %@",[NSThread currentThread]);

    //异步执行任务

    for (NSInteger i = 0; i < 10; i++) {

        dispatch_async(queue, ^{

            [NSThread sleepForTimeInterval:0.5];

            NSLog(@"%zd -- %@", i,[NSThread currentThread]);

        });

    }

    

    NSLog(@"thread stop %@",[NSThread currentThread]);

 

}

执行结果:

2017-10-24 10:07:44.857 GCDTest[1700:341404] thread start {number = 1, name = main}

2017-10-24 10:07:44.857 GCDTest[1700:341404] thread stop {number = 1, name = main}

2017-10-24 10:07:45.361 GCDTest[1700:341469] 1 -- {number = 3, name = (null)}

2017-10-24 10:07:45.361 GCDTest[1700:341468] 2 -- {number = 5, name = (null)}

2017-10-24 10:07:45.361 GCDTest[1700:341486] 0 -- {number = 4, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341489] 4 -- {number = 7, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341471] 3 -- {number = 6, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341490] 5 -- {number = 8, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341491] 6 -- {number = 9, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341494] 9 -- {number = 10, name = (null)}

2017-10-24 10:07:45.362 GCDTest[1700:341493] 8 -- {number = 12, name = (null)}

 

2017-10-24 10:07:45.362 GCDTest[1700:341492] 7 -- {number = 11, name = (null)}

从执行结果可以看出,thread startthread stop是在主线程中完成,其他的开了多个队列再执行,至于具体的任务在哪条线程上执行,这就是GCD底层控制的,所以这也就说明了GCD不能叫做多线程,只能叫并发编程。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值