理解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不能叫做多线程,只能叫并发编程。
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不能叫做多线程,只能叫并发编程。
相关文章推荐
- GCD任务、队列理解
- 深入理解Spark 2.1 Core (七):Standalone模式任务执行的原理与源码分析
- GCD--队列的类型和执行任务方式的四种的排列组合
- 深入理解Spark 2.1 Core (七):任务执行的原理与源码分析
- GCD之主队列、全局并发队列、以及同步任务的执行
- 苹果多线程网络编程之-GCD队列与任务的理解
- GCD中各种队列和任务执行方式的组合
- 关于GCD执行任务的理解
- GCD:dispatch_sync会在当前线程中执行派发到其他队列的任务
- GCD编程dispatch_sync(同步)和dispatch_async(异步)方式执行并发队列任务区别
- MapReduce调度与执行原理之任务调度
- var和let在异步任务队列中的执行差异
- 线程池中任务队列SynchronousQueue的理解
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
- GCD6: 在GCD上异步执行非UI相关任务
- GCD使用 串行并行队列 与 同步异步执行的各种组合 及要点分析
- 从jvm解释器的执行原理理解局部变量与操作数栈
- IOS开发(62)之GCD上异步执行非UI任务
- android 基本任务 的执行原理分析
- GCD4: 用GCD执行与UI相关的任务