dispatch queue 的一些理解

想向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>


猜一下打印顺序:虽然有时间控制,但是因为是串行的queue,所以 三个task的顺序 就是 1in 1 out , 2 in  2 out ,3 in 3 out。

好的,打印下看看:

<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>

恩,不错,那我们再试试 concurrent queue

<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>

猜想一下:因为是并行的,因为是测试现在系统不紧张,所以会有三个线程,根据休眠时间判定  3  2  1 (先执行完)

打印下:

<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>

猜想下:因为先使用sync,所以阻塞当前线程,直到任务结束 输出 
<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>


那我们在使用concurrent queue 试试

<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。




你可能感兴趣的:(gcd,dispatch_queue)