GCD中任务与队列(一)

来源:互联网 发布:淘宝老店铺 编辑:程序博客网 时间:2024/05/19 08:44

首先,GCD是一套基于C的并发编程(其实并不能理解为多线程,因为这个并不是自己来控制线程),使用的时候,我们不需要管理线程的任何生命周期,系统会自动帮我们管理。首先在底层是有一个任务队列与线程池的概念,如果这个不懂,百度一下先。其次先理解以下几个概念。
1、同步、异步
同步:表示在当前线程(注意:不一定就表示主线程)执行任务,不去线程池中拿线程
异步:表示不在当前线程执行任务,需要去线程池拿线程做处理
2、串行、并发
串行:表示所有任务一个接一个的在线程中执行
并发:表示所有任务可以同时在不同线程上执行
可能这样粗略讲解一下,还是不够清晰,先我们这样理解一下,同步,异步是用来表示是否需要去线程池中取线程,而串行、并发是用来表示怎么去任务队列中取任务的。
下面我们组合一下上面两种方式通过代码来一一讲解。
1、同步、串行 (在当前线程中一个一个的执行任务)

/** 串行、同步 */- (void)demo1 {    //创建一个串行队列    dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_SERIAL);    NSLog(@"start ==>> %@", [NSThread currentThread]);    //同步执行任务    for (NSInteger i = 0; i < 10; i++) {        dispatch_sync(queue, ^{            [NSThread sleepForTimeInterval:0.5];            NSLog(@"%zd -- %@", i, [NSThread currentThread]);        });    }    NSLog(@"stop ==>> %@", [NSThread currentThread]);}

执行结果:

2017-09-01 14:04:22.728 GCDTest[15085:1120147] start ==>> <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:23.230 GCDTest[15085:1120147] 0 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:23.731 GCDTest[15085:1120147] 1 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:24.232 GCDTest[15085:1120147] 2 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:24.733 GCDTest[15085:1120147] 3 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:25.234 GCDTest[15085:1120147] 4 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:25.736 GCDTest[15085:1120147] 5 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:26.236 GCDTest[15085:1120147] 6 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:26.738 GCDTest[15085:1120147] 7 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.238 GCDTest[15085:1120147] 8 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.739 GCDTest[15085:1120147] 9 -- <NSThread: 0x600000064c80>{number = 1, name = main}2017-09-01 14:04:27.739 GCDTest[15085:1120147] stop ==>> <NSThread: 0x600000064c80>{number = 1, name = main}

从执行结果可以看到,所有任务都是一个一个的执行.
2、异步串行 (会去线程池拿线程,但是任务顺序执行)

/** 串行、异步 */- (void)demo2 {    //创建一个串行队列    dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_SERIAL);    NSLog(@"start ==>> %@", [NSThread currentThread]);    //同步执行任务    for (NSInteger i = 0; i < 10; i++) {        dispatch_async(queue, ^{            [NSThread sleepForTimeInterval:0.5];            NSLog(@"%zd -- %@", i, [NSThread currentThread]);        });    }    NSLog(@"stop ==>> %@", [NSThread currentThread]);}

执行结果:

2017-09-01 14:09:43.919 GCDTest[15254:1145817] start ==>> <NSThread: 0x610000070080>{number = 1, name = main}2017-09-01 14:09:43.919 GCDTest[15254:1145817] stop ==>> <NSThread: 0x610000070080>{number = 1, name = main}2017-09-01 14:09:44.422 GCDTest[15254:1146187] 0 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:44.926 GCDTest[15254:1146187] 1 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:45.430 GCDTest[15254:1146187] 2 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:45.930 GCDTest[15254:1146187] 3 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:46.435 GCDTest[15254:1146187] 4 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:46.940 GCDTest[15254:1146187] 5 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:47.441 GCDTest[15254:1146187] 6 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:47.945 GCDTest[15254:1146187] 7 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:48.453 GCDTest[15254:1146187] 8 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}2017-09-01 14:09:48.956 GCDTest[15254:1146187] 9 -- <NSThread: 0x61800006cf80>{number = 3, name = (null)}

由以上结果可以知道,start、stop 在主线程中执行完成,其他的开辟了一个子线程执行
3、同步并发 (在当前队列执行,可以同时取出多个任务(取出那么多任务,只有一个线程,有鸟用))上代码

/** 并发、同步 */- (void)demo3 {    //创建一个串行队列    dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_CONCURRENT);    NSLog(@"start ==>> %@", [NSThread currentThread]);    //同步执行任务    for (NSInteger i = 0; i < 10; i++) {        dispatch_sync(queue, ^{            [NSThread sleepForTimeInterval:0.5];            NSLog(@"%zd -- %@", i, [NSThread currentThread]);        });    }    NSLog(@"stop ==>> %@", [NSThread currentThread]);}

执行结果:

2017-09-01 14:14:02.972 GCDTest[15403:1168682] start ==>> <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:03.473 GCDTest[15403:1168682] 0 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:03.974 GCDTest[15403:1168682] 1 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:04.476 GCDTest[15403:1168682] 2 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:04.976 GCDTest[15403:1168682] 3 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:05.477 GCDTest[15403:1168682] 4 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:05.978 GCDTest[15403:1168682] 5 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:06.478 GCDTest[15403:1168682] 6 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:06.979 GCDTest[15403:1168682] 7 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.481 GCDTest[15403:1168682] 8 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.982 GCDTest[15403:1168682] 9 -- <NSThread: 0x618000078380>{number = 1, name = main}2017-09-01 14:14:07.982 GCDTest[15403:1168682] stop ==>> <NSThread: 0x618000078380>{number = 1, name = main}

看上面就知道,所有任务都在主线程中执行,所以取出来的任务还是得等待
4、并发、异步(拿线程,同时拿任务) 这才是多线程的精髓,上代码

/** 并发、异步 */- (void)demo4 {    //创建一个串行队列    dispatch_queue_t queue = dispatch_queue_create("demo1", DISPATCH_QUEUE_CONCURRENT);    NSLog(@"start ==>> %@", [NSThread currentThread]);    //同步执行任务    for (NSInteger i = 0; i < 10; i++) {        dispatch_async(queue, ^{            [NSThread sleepForTimeInterval:0.5];            NSLog(@"%zd -- %@", i, [NSThread currentThread]);        });    }    NSLog(@"stop ==>> %@", [NSThread currentThread]);}

执行结果

2017-09-01 14:20:28.223 GCDTest[15696:1210937] start ==>> <NSThread: 0x600000076900>{number = 1, name = main}2017-09-01 14:20:28.223 GCDTest[15696:1210937] stop ==>> <NSThread: 0x600000076900>{number = 1, name = main}2017-09-01 14:20:28.223 GCDTest[15696:1211285] 1 -- <NSThread: 0x608000077940>{number = 3, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211286] 3 -- <NSThread: 0x600000079340>{number = 6, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211307] 2 -- <NSThread: 0x600000079280>{number = 5, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211306] 0 -- <NSThread: 0x61000007a300>{number = 4, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211288] 4 -- <NSThread: 0x61000007a140>{number = 7, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211563] 5 -- <NSThread: 0x6180000794c0>{number = 8, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211564] 6 -- <NSThread: 0x600000079300>{number = 9, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211565] 7 -- <NSThread: 0x600000079480>{number = 10, name = (null)}2017-09-01 14:20:28.223 GCDTest[15696:1211285] 8 -- <NSThread: 0x608000077940>{number = 3, name = (null)}2017-09-01 14:20:28.224 GCDTest[15696:1211286] 9 -- <NSThread: 0x600000079340>{number = 6, name = (null)}

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

阅读全文
0 0