GCD中任务与队列(一)

xiaoxiao2021-02-28  84

首先,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不能叫做多线程,只能叫并发编程

转载请注明原文地址: https://www.6miu.com/read-79556.html

最新回复(0)