iOS多线程之GCD

1.什么是GCD

Grand Central Dispatch(GCD)是异步执行任务的技术之一。提供了对底层线程管理的实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就会生成必要的线程并计划执行任务。
dispatch_async(queue,^
{
    /*
     *执行任务
     */
});

2.Dispatch Queue

Dispatch Queue是执行处理的FIFO(先进先出)等待队列,按照执行处理的方式分为Serial Dispatch Queue和Concurrent Dispatch Queue。Serial Dispatch Queue只使用一个线程来执行处理,要等待现在执行中的处理结束才会执行下一个处理,Concurrent Dispatch Queue采用多个线程来执行处理,不等待现在执行中的处理结束,具体的线程数由iOS和OSX的内核--XNU决定,XUN动态的根据要执行的任务数来增加和减少线程。
创建Serial Dispatch Queue
dispatch_queue_t serialDispatchQueue = dispatch_queue_create("SerialDispatchQueueName",NULL);
dispatch_async(serialDispatchQueue,^
{
});
dispatch_release(serialDispatchQueue);
创建Concurrent Dispatch Queue
dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create("ConcurrentDispatchQueueName",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentDispatchQueue,^
{
});
dispatch_release(concurrentDispatchQueue);

2.1 Main Dispatch Queue

Main Dispatch Queue是在主线程Runloop中执行处理的Serial Dispatch Queue。
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();

2.2 Global Dispatch Queue

Global Dispatch Queue是Concurrent Dispatch Queue,Global Dispatch Queue有四个执行优先级,分别是高优先级(High Priority)、默认优先级(Default Priority)、低优先级(Low Priority)和后台优先级(Background Priority)。获取方法如下:
//高优先级 Global Dispatch Queue
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
//默认优先级 Global Dispatch Queue
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//低优先级 Global Dispatch Queue
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);
//后台优先级 Global Dispatch Queue
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

2.3 常用的Main和Global模型

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^()
{
    //并行处理任务
    dispatch_async(dispatch_get_main_queue(),^()
    {
        //主线程中执行处理
    });
});

3.GCD的API

3.1 dispatch_after

dispatch_after并不是在指定的时候后执行处理,而只是在指定的时间后追加处理到指定的Dispatch Queue,具体执行时间还要看当前线程的执行情况,3秒后追加指定的Block到Main Dispatch Queue中执行:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);
dispatch_after(time,dispatch_get_main_queue,^()
{
    //3秒后的处理
});

3.2 dispatch_once

dispatch_once函数保证在应用程序的生命周期内只执行一次指定处理的API,单例的实现中常用到。使用方式如下:
static dispatch_once_t token;
dispatch_once(&token,^()
{
});

3.3 Dispatch Group

Dispatch Group主要是用于在追加到Dispatch Queue中的多个处理全部处理结束后想执行结束处理的情况,最后想要执行的结束处理的追加可以采用同步(dispatch_group_wait())或者异步(dispatch_group_notify())两种方式。dispatch_group_wait()会阻塞该函数调用的线程,直到添加到Group中的处理全部执行完毕才执行结束处理,而dispatch_group_notify()不会阻塞,会立刻返回,当追加到Group中的所有处理都执行完成的时候,会将指定的Block追加到指定的Dispatch Queue中。具体Dispatch Group使用方式如下:
异步:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{ NSLog(@"TestBlock1"); });
dispatch_group_async(group,queue,^{ NSLog(@"TestBlock2"); });

dispatch_group_notify(group,dispatch_get_main_queue(),^{ NSLog(@"Done"); });
同步:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{ NSLog(@"TestBlock1"); });
dispatch_group_async(group,queue,^{ NSLog(@"TestBlock2"); });

dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
NSLog(@"Done");

3.4 dispatch_sync

dispatch_async是异步的追加Block到指定的Dispatch Queue中,不会阻塞当前函数的线程。而dispatch_sync会阻塞当前函数调用的线程直到追加的Block执行完成。dispatch_sync的功能类似于dispatch_group_wait,阻塞当前线程直到另外一个线程完成了追加的Block的执行,如果当前线程和要处理Block的线程相同,就会造成线程死锁。死锁代码如下:
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue,^
{
    dispatch_sync(queue,^{ NSLog(@"线程死锁"); });
});

3.5 dispatch_apply

dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联API,该函数按指定次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束后返回。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY,0);
dispatch_apply(10,queue,^(size_t index)
{
    NSLog(@"%zu",index);
});
NSLog(@"Done");

3.6 dispatch_barrier_async

dispatch_barrier_async主要是和Concurrent Dispatch Queue结合起来使用,起到线程中栅栏的作用,等待该函数调用之前所有添加到Dispatch Queue中的处理执行完成之后才执行该函数要添加的处理,在该函数添加的处理执行完成后,后续添加到Dispatch Queue的处理才能执行。
dispatch_queue_t queue = dispatch_queue_create(@"ConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue,Block1ForReading);
dispatch_async(queue,Block2ForReading);
dispatch_async(queue,Block3ForReading);
dispatc_barrier_async(queue,BlockForWriting);
dispatch_async(queue,Block4ForReading);
dispatch_async(queue,Block5ForReading);
dispatch_async(queue,Block6ForReading);
dispatch_release(queue);

3.7 dispatch_set_target_queue

dispatch_set_target_queue可以用来改变目标Dispatch Queue的优先级为目标Dispatch Queue的优先级。
dispatch_queue_t myQueue = dispatch_queue_create(@"myQueue",0);
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
dispatch_set_target_queue(myQueue,globalQueue);

3.8 dispatch_suspend / dispatch_resume

dispatch_suspend函数挂起指定的Dispatch Queue
dispatch_suspend(queue);
dispatch_resume会恢复指定的Dispatch Queue
dispatch_resume(queue);

3.9 Dispatch Semaphore

GCD提供了线程的信号量处理函数:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semaphore);

参考链接:

1.iOS多线程编程3/3 - GCD

2.Concurrent Programming Guide

iOS多线程之GCD,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。