您的位置:首页 > 其它

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

2017-10-23 22:24 483 查看
我们都知道IOS中常用于处理线程的三种方式:NSThread、NSOperation、GCD,而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]);

        });

   
4000
 }

    

    [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 start、thread 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 start,thread stop是在主线程中完成,其他的开了多个队列再执行,至于具体的任务在哪条线程上执行,这就是GCD底层控制的,所以这也就说明了GCD不能叫做多线程,只能叫并发编程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息