想向iOS高级进阶,学习一些线程只是是必不可少的。
GCD的威力强大,却又难以想象的简洁,苹果这种手法真是碉堡了!膜拜!
记录个博客,简单分享下关于dispatch_queue的一些理解
dispatch_queue 分两种:dispatch_queue_serial (串行) , dispatch_queue_concurrent(并行);
创建这两种不同的queue使用:
<span style="font-size:14px;background-color: rgb(255, 255, 255);"> dispatch_queue_t concurrentQueue = dispatch_queue_create("test.sync.queue", DISPATCH_QUEUE_CONCURRENT); </span>
<span style="font-size:14px;background-color: rgb(255, 255, 255);"> dispatch_queue_t serilQueue = dispatch_queue_create("test.sync.queue", DISPATCH_QUEUE_SERIAL); </span>
第一问 那serial跟concurrent有什么区别?
这两种queue都是遵循FIFO(first in first out),任务都是按照顺序执行。
不同的是,serial queue 只持有一个线程,所有的task都等待在它之前的task完成;
concurrent queue 会根据系统状态持有多个线程。
这里需要说下concurrent queue的情况,假设该queue现在持有3个线程 a b c,以此添加了5个任务1 2 3 4 5,执行顺序就是 ,任务1添加到a , 任务2看到任务1被执行,不等任务1结束,就榜上线程b,开始风花雪月,同样任务3也不甘寂寞,榜上线程c ,注意,此时,由于abc都在度蜜月,所以任务4 5只能羡慕嫉妒恨,干等到abc回复单身。好的,如果此时b先结束任务2,那么任务4就找准机会,鸠占鹊巢,跟b好上了,任务5继续等,直到a c中的任务 1 3 有一个先结束,假设1先结束,那么 执行列表就是
a b c
1 2 3
5 4
恩,大概就是这么个意思。
现在写写代码测试下:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">+ (void)testSync { //对于串行的queue,只会开启一个线程执行任务,按照FIFO的原则 dispatch_queue_t serilQueue = dispatch_queue_create("test.sync.queue", DISPATCH_QUEUE_SERIAL); dispatch_async(serilQueue, ^{ NSLog(@"task 1 in"); [NSThread sleepForTimeInterval:3.f]; NSLog(@"task 1 out"); }); dispatch_async(serilQueue, ^{ NSLog(@"task 2 in"); [NSThread sleepForTimeInterval:2.f]; NSLog(@"task 2 out"); }); dispatch_async(serilQueue, ^{ NSLog(@"task 3 in"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"task 3 out"); }); } </span>
好的,打印下看看:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">2014-11-13 10:44:45.422 TUPIAN[1888:47361] task 1 in 2014-11-13 10:44:48.424 TUPIAN[1888:47361] task 1 out 2014-11-13 10:44:48.424 TUPIAN[1888:47361] task 2 in 2014-11-13 10:44:50.426 TUPIAN[1888:47361] task 2 out 2014-11-13 10:44:50.426 TUPIAN[1888:47361] task 3 in 2014-11-13 10:44:51.427 TUPIAN[1888:47361] task 3 out</span>
<span style="font-size:14px;background-color: rgb(255, 255, 255);">+ (void)testAsync{ //对于并行的queue,根据任务开启多个线程,也是遵循FIFO的原则,但是task 2 不会等待task 1 结束才执行,而是在task 1 开启之后立即执行 //所谓的立即执行是在 DISPATCH_QUEUE_CONCURRENT 分配到至少两个线程的基础上,如果由于系统紧张,只分配了一个县城,task 2 还是会等待 task1 结束 dispatch_queue_t concurrentQueue = dispatch_queue_create("test.sync.queue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(concurrentQueue, ^{ NSLog(@"task 1 in"); [NSThread sleepForTimeInterval:3.f]; NSLog(@"task 1 out"); }); dispatch_async(concurrentQueue, ^{ NSLog(@"task 2 in"); [NSThread sleepForTimeInterval:2.f]; NSLog(@"task 2 out"); }); dispatch_async(concurrentQueue, ^{ NSLog(@"task 3 in"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"task 3 out"); }); } </span>
打印下:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">2014-11-13 10:51:20.223 TUPIAN[2080:51461] task 1 in 2014-11-13 10:51:20.223 TUPIAN[2080:51464] task 2 in 2014-11-13 10:51:20.223 TUPIAN[2080:51463] task 3 in 2014-11-13 10:51:21.226 TUPIAN[2080:51463] task 3 out 2014-11-13 10:51:22.225 TUPIAN[2080:51464] task 2 out 2014-11-13 10:51:23.226 TUPIAN[2080:51461] task 1 out</span>
第二问 :现在queue基本上了解,那 dispatch_sync 和 dispatch_async 有什么区别呢
答:他俩的区别就是相对于当前向我们创建的queue中追加任务的queue来说,是同步调用还是异步调用。
恩,有点长,我们来分开说,假设,我们现在在主线程上加载一个大图,高清无码的,不使用第三方库,自己写,为了不阻塞主线程我们创建一个串行的queue,叫 queueA, 另一个queue就是我们的MainQueue,那么queueA就是想对于MainQueue来说是同步还是异步了,同步就阻塞MainQueue,等待;异步立即返回,不等待。
好的,加个代码测试下:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">+ (void)testAsyncAndSync{ dispatch_queue_t serialQueue = dispatch_queue_create("test.async+sync.queue", DISPATCH_QUEUE_SERIAL); dispatch_sync(serialQueue, ^{ [NSThread sleepForTimeInterval:5.f]; NSLog(@"sync sleep 5.f"); }); dispatch_async(serialQueue, ^{ NSLog(@"task 2 "); }); }</span>
<pre name="code" class="objc"><span style="font-size:14px;background-color: rgb(255, 255, 255);">sync sleep 5.f</span>然后在输出
<span style="font-size:14px;background-color: rgb(255, 255, 255);">task 2</span>
查看下实际结果:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">2014-11-13 11:07:30.385 TUPIAN[2127:56886] sync sleep 5.f 2014-11-13 11:07:30.387 TUPIAN[2127:56923] task 2 </span>
<span style="font-size:14px;background-color: rgb(255, 255, 255);">+(void)testConcurrentQueueAsyncAndSync { dispatch_queue_t concurrentQueue = dispatch_queue_create("test.async+sync.queue", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(concurrentQueue, ^{ [NSThread sleepForTimeInterval:5.f]; NSLog(@"sync sleep 5.f"); }); dispatch_async(concurrentQueue, ^{ NSLog(@"task 2 "); }); }</span>
<pre name="code" class="objc"><span style="font-size:14px;background-color: rgb(255, 255, 255);">sync sleep 5.f</span>然后在输出
<span style="font-size:14px;background-color: rgb(255, 255, 255);">task 2</span>
实际打印:
<span style="font-size:14px;background-color: rgb(255, 255, 255);">2014-11-13 11:10:23.417 TUPIAN[2157:58248] sync sleep 5.f 2014-11-13 11:10:23.418 TUPIAN[2157:58317] task 2 </span>
这里总结下,如果是想对于任务之间操作就是控制queue是并行还是串行 , 如果是想相对于当前线程就控制函数 dispatch_async还是dispatch_sync。