多线程GCD

来源:互联网 发布:300英雄官方淘宝店 编辑:程序博客网 时间:2024/04/28 15:54

GCD
—学习任何技术都应该先从基本概念,常见用法,和注意事项入手,如果没有基本概念就不会有更加深层的理解和体会,这是一种源于外而生于内的感知。那就不扯啦!

一:基本概念
全称是Grand Central Dispatch,可译为“伟大的中枢调度器”。
既然是调度器,它就像一个管理者,哪个线程应该做什么不应该做什么都有它管理。并且是C语言的非常之牛逼。
自从苹果iOS4推出GCD之后,吸引了越来越多的开发者。它能充分利用设备的多核,为并行运算提供了解决方案。

GCD最重要的概念就是:任务和队列。
任务:执行什么操作,就是你想做什么;
队列:用来存放任务的;

二:用法
第一步:确定你要做的事情,哪些耗时操作;
第二步:把你想做的任务放到队列中,这就OK啦;
GCD会将你放在队列中的任务取出来,放到对应的线程中去执行,这不需要你手动操作;
原则:先进先出,后进后出。也就是说如果一个任务先放进队列,他就被先取出来;
注:虽然先进先出,但并不代表先出来的任务就一定先完成,有可能先出来的任务,可能最后才完成,这取决于看哪个任务跑的快。

三:既然GCD是C语言的,那我们就要学学系统给我们提供了哪些常用函数以及队列的基本认识:

  1. 同步函数,以同步的方式执行任务
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);queue:队列block:任务

同步:只能在当前线程中执行任务,不具备开启线程的能力, 也就是说该函数在哪个线程里面,后面block(你的耗时操作)就会在哪个线程里面执行。

2.异步函数,以异步的方式执行任务

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

异步:具备开启线程的能力,可以在开启新的线程中执行任务。

3.队列
GCD的队列分为两大类型
a.并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只有在异步(dispatch_async)函数下才有效

b.串行队列(Serial Dispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

四:基本用法

  1. 首先我们先看异步函数的并发队列,这个在开发中用的较多
 dispatch_async(dispatch_queue_t queue, dispatch_block_t block)//用于创建线程,后面的block就是我们要放的任务,

看这个函数,我们就知道首先要有队列,在GCD中队列即可以手动创建,也可以获取(这个是系统已经为我们创建好的,直接给开发者用),我们先看自己手动创建的。
我们创建队列用下面这个函数

  dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>) //const char *label:队列的名称,你可以理解成唯一标识(这个开发者可以自己命名,最好唯一) //dispatch_queue_attr_t attire:队列的类型,这个一般就取两个值,并发队列(DISPATCH_QUEUE_CONCURRENT)和串行队列(DISPATCH_QUEUE_SERIAL)

举例:

//创建一个队列dispatch_queue_t queue = dispatch_queue_create("I love you", DISPATCH_QUEUE_CONCURRENT);//把所需的任务加入到队列中  dispatch_async(queue, ^{        NSLog(@"%@",[NSThread currentThread]);    });//你可以把很多任务都加进去

刚刚说啦你也可以直接获得全局的并发队列,用下面的函数

dispatch_get_global_queue(<#long identifier#>, <#unsigned long flags#>)//long identifier:队列的优先级,如果有很多队列,优先级高者先执行,因为如果你获得很多全局队列。系统就不知道先执行哪一个好,所以要用优先级,优先级有四个:#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台一般我们给个默认的就OK。//unsigned long flags); // 此参数为未来准备的,暂时用不到 ,用0即可

举例:

//获得全局的并发队列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 把任务加到队列中 dispatch_async(queue, ^{        NSLog(@"%@",[NSThread currentThread]);    });

2.异步函数的串行队列:既然是异步函数,说明具备开启线程的能力(会开启一条新的线程),串行队列说明任务一个一个的执行。在开发中也较常用,因为我们总是会碰到几个任务比较耗时,但还要要求顺序。

//1.创建串行队列    dispatch_queue_t queue = dispatch_queue_create("I love you", DISPATCH_QUEUE_SERIAL); // 2.将任务加入队列    dispatch_async(queue, ^{        NSLog(@"%@",[NSThread currentThread]);    });

3.同步函数的并发队列:同步函数不具备开启线程的能力

//1.创建并行队列    dispatch_queue_t queue = dispatch_queue_create("I love you", DISPATCH_QUEUE_CONCURRENT);    // 2.将任务加入队列    dispatch_sync(queue, ^{        NSLog(@"%@",[NSThread currentThread]);    });

4.同步函数的串行队列:同步函数不具备开启线程的能力,任务一个一个执行。

//1.创建串行队列    dispatch_queue_t queue = dispatch_queue_create("I love you", DISPATCH_QUEUE_SERIAL);    // 2.将任务加入队列    dispatch_sync(queue, ^{        NSLog(@"%@",[NSThread currentThread]);    });//#define DISPATCH_QUEUE_SERIAL NULL 串行队列也可以直接传NULL

5.还有一种队列比较特殊就是主队列,放在组队列里面的任务,都会放在主线程中执行,使用dispatch_get_main_queue()获得主队列。

a.异步函数的主队列:只在主线程中执行

// 获得主队列    dispatch_queue_t queue = dispatch_get_main_queue();// 将任务加入队列    dispatch_async(queue, ^{        NSLog(@"%@", [NSThread currentThread]);    });

b.同步函数的主队列会造成线程的阻塞。

五.GCD中常用函数

a.延迟执行

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{    // 10秒后执行这里的代码...});//此队列为主队列,也就是说,该block里面的代码会在主线程中执行,当然你也可以自己创建一个并发队列。

b.使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次

static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{    // 只执行1次的代码(这里面默认是线程安全的)});

c.GCD中执行任务的函数

dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);//该函数用于把前面的任务执行完毕后,才执行该任务,并且等把该任务执行完毕后,才执行后面的任务。// 该函数的队列,必须手动创建,不要获取系统提供的队列,否则有时不好使。

关于GCD方面的内容,将持续更新!

1 0