使用GCD实现多线程队列

来源:互联网 发布:python 字符串 查找 编辑:程序博客网 时间:2024/05/17 02:15

GCD的两个核心概念如下。
1,队列:队列负责管理开发者提交的任务,GCD队列始终以FIFO(先进先出)的方式来处理任务——但由于任务的执行时间并不相同,因此先处理的任务并不一定先结束。队列既可以是串行队列,也可以是并发队列,串行队列每次只处理一个任务,必须前一个任务执行完后,才能执行下一个任务;并发队列则可同时处理多个任务,因此将会有多个任务并发执行。
队列底层会维护一个线程池来处理用户提交的任务,线程池的作用就是执行队列管理的任务。串行队列底层的线程池只要维护一个线程即可,并发队列的底层则需要维护多个线程。
2,任务:任务就是用户提交给队列的工作单元,这些任务将会提交给队列底层维护的线程池执行,因此这些任务会以多线程的方式执行。

对于打算使用GCD实现多线程的开发者来说,使用GCD只要遵守两个步骤即可。
1,创建队列。
2,将任务提交给队列。

创建队列
GCD的队烈可分为两种。
1,串行队列:串行队列底层的线程池只要一个线程,因此只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束后才能开始执行。
2,并发队列: 线程池提供多个线程来执行任务,所以可以按FIFO的顺序并发启动,执行多个并发任务。
下面函数用于创建或访问队列。

1, dispatch_queue_t dispatch_get_current_queue(void) : 获取当前执行代码所在的队列。
2,dispatch_queue_t dispatch_get_global_queue(long priority,unsigned flags):根据指定优先级、额外的旗标来获取系统的全局并发队列。第一个参数可接受DISPATCH_QUEUE_PRIORITY_HIGH(2)、DISPATCH_QUEUE_PRIORITY_DEFAULT(0)、DISPATCH_QUEUE_PRIORITY_LOW(-2) 和DISPATCH_QUEUE_PRIORITY_BACKGROUND这几个优先级。目前第2参数(额外的旗标参数)暂未使用,只是为将来做准备的,一般传入0即可。
3, dispatch_queue_t dispatch_get_main_queue(void) : 获取应用主线程所关联的串行队列。
4,dispatch_queue_t dispatch_queue_create(const char *label,dipatch_queue_attr_t attr) :根据指定自负串标签创建队列。第二个参数可控制创建串行队列还是并发队列,如果将第二个参数设为 “DISPATCH_QUEUE_SERIAL”,则代表创建串行队列:如果将第2个参数设为“DISPATCH_QUEUE_CONCURRENT”,则代表创建并发队列。在没有启用ARC机制的情况下,通过这种方式创建的队列需要调用dispatch_release()函数释放引用计数。
5,const char *dispatch_queue_get_label(dispatch_queue_t queue) :获取指定队列的字符串标签。上面函数中涉及一个dispatch_queue_t,这种类型就代表一个队列。

根据上面函数,程序可以创建如下几种队列。
1,获取系统默认的全局并发队列
获取系统默认的全局并发队列可通过如下代码完成。

dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

2,获取系统主线程关联的串行队列。
获取系统主线程关联的串行队列可通过如下代码完成:

dispatch_queue_t queue = dispatch_get_main_queue();

3,创建串行队列
创建串行队列可通过如下代码完成:

dispatch_queue_t queue = dispatch_queue_create("jkIOS.queue",DISPATCH_QUEUE_SERIAL);

如果将多个任务提交给串行队列,多个任务只能按顺序执行,必须等前一个任务完成后,才能开始执行后一个任务。
4,创建并发队列
创建并发队列可通过如下代码完成:

 dispatch_queue_t queue = dispatch_queue_create("jkIOS.queue",DISPATCH_QUEUE_CONCURRENT);

如果将多个任务提交给并发队列,并发队列可以按照FIFO的顺序启动多个并发执行的任务,由于任务的耗时长短并不相同,因此后提交的任务完全可能先完成。
异步提交任务
iOS提供了如下函数来向队列提交任务。下面很多函数都有两个版本:一个接收代码块作为参数的版本,一个接收函数作为 参数的版本——其中接受函数作为参数的函数名最后多了_f后缀,而且会多一个参数,用于向函数传入应用程序定义的上下文。
1,void dispatch_async(dispatch_t queue,dispatch_block_t block) : 将代码块以异步方式提交给指定队列,该队列底层的线程池将负责执行该代码块。
2,void dispatch_async_f(dispatch_queue_t queue,void *context,dispatch__function_t work) : 将函数以异步方式提交给指定队列,该队列底层的线程池将负责执行该函数。
3, void dispatch_sync(dispatch_queue_t queue,dispatch_block_t block) : 将代码块以同步方式提交给指定队列,该队列底层的线程池将负责执行该代码块。
4,void dispatch_sync_f(dispatch_queue,void *context,dispatch_function_t work) : 将函数以同步方式提交给指定队列,该队列底层的线程池将负责执行该函数。
5,void dispatch_after(dispatch_time_t when,dispatch_queue_t queue,dispatch_block_t block) : 将函数以异步方式提交给指定队列,该队列底层的线程池将负责在when指定的时间点执行该代码块。
6, void dispath_after_f(dispatch_time_t when,dispatch_queue_t queue,void *context,dispatch_function_t work) : 将函数以异步方式提交给队列,该队列底层的线程池将负责在when指定的时间点执行该函数。
7,void dispatch_apply(size_t iterations,dispatch_queue_t queue,void(^block)(size_t)) :将代码块以异步方式提交给指定队列,该队列底层的线程池将会多次重复执行该代码块。
8,void dispatch_apply_f(size_t iteradions,dispatch_queue_t queue,void *context,coid (*work)(void *,size_t)) :将函数以异步的方式提交给指定队列,该队列底层的线程池将会多次重复执行该函数。
9,void dispatch_once(dispatch_once_t *predicate,dispatch_block_t block) :将代码块提交给指定队列,该队列底层的线程池控制在应用生命周期内仅执行一次。其中predicate参数是一个指向dispatch_once_t(本质就是long型整数)变量的指针,该变量用于判断该代码块是否已经执行过。
演示代码如下:

#import "FKViewController.h"@interface FKViewController ()@end@implementation FKViewController// 定义2个队列dispatch_queue_t serialQueue;dispatch_queue_t concurrentQueue;- (void)viewDidLoad{    [super viewDidLoad];    // 创建串行队列    serialQueue = dispatch_queue_create("fkjava.queue", DISPATCH_QUEUE_SERIAL);    // 创建并发队列    concurrentQueue = dispatch_queue_create("fkjava.queue"        , DISPATCH_QUEUE_CONCURRENT);}- (IBAction)serial:(id)sender{    // 依次将2个代码块提交给串行队列    // 必须等到第1个代码块完成后,才能执行第2个代码块。    dispatch_async(serialQueue, ^(void)    {        for (int i = 0 ; i < 10; i ++)        {            NSLog(@"%@=====%d"  , [NSThread currentThread] , i);        }    });    dispatch_async(serialQueue, ^(void)    {        for (int i = 0 ; i < 10; i ++)        {            NSLog(@"%@------%d" , [NSThread currentThread] , i);        }    });}- (IBAction)concurrent:(id)sender{    // 依次将2个代码块提交给并发队列    // 两个代码块可以并发执行    dispatch_async(concurrentQueue, ^(void)    {        for (int i = 0 ; i < 10; i ++)        {            NSLog(@"%@=====%d"  , [NSThread currentThread] , i);        }    });    dispatch_async(concurrentQueue, ^(void)    {        for (int i = 0 ; i < 10; i ++)        {            NSLog(@"%@------%d" , [NSThread currentThread] , i);        }    });}@end

触发串行按钮的运行结果如下:

2015-12-21 10:13:16.660 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====02015-12-21 10:13:16.661 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====12015-12-21 10:13:16.661 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====22015-12-21 10:13:16.661 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====32015-12-21 10:13:16.662 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====42015-12-21 10:13:16.662 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====52015-12-21 10:13:16.662 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====62015-12-21 10:13:16.663 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====72015-12-21 10:13:16.663 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====82015-12-21 10:13:16.663 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}=====92015-12-21 10:13:16.663 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------02015-12-21 10:13:16.664 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------12015-12-21 10:13:16.664 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------22015-12-21 10:13:16.664 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------32015-12-21 10:13:16.664 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------42015-12-21 10:13:16.664 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------52015-12-21 10:13:16.665 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------62015-12-21 10:13:16.665 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------72015-12-21 10:13:16.665 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------82015-12-21 10:13:16.665 queueTest[26514:4985585] <NSThread: 0x7fbdfb52f450>{number = 2, name = (null)}------9

触发并发按钮的运行结果如下:

2015-12-21 10:15:16.321 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====02015-12-21 10:15:16.322 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------02015-12-21 10:15:16.323 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====12015-12-21 10:15:16.323 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------12015-12-21 10:15:16.323 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====22015-12-21 10:15:16.323 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------22015-12-21 10:15:16.324 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------32015-12-21 10:15:16.324 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====32015-12-21 10:15:16.324 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------42015-12-21 10:15:16.324 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====42015-12-21 10:15:16.325 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====52015-12-21 10:15:16.325 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------52015-12-21 10:15:16.325 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====62015-12-21 10:15:16.325 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------62015-12-21 10:15:16.326 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------72015-12-21 10:15:16.326 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====72015-12-21 10:15:16.326 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------82015-12-21 10:15:16.326 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====82015-12-21 10:15:16.326 queueTest[26520:4986593] <NSThread: 0x7fa460738940>{number = 3, name = (null)}------92015-12-21 10:15:16.326 queueTest[26520:4986592] <NSThread: 0x7fa46060cb90>{number = 2, name = (null)}=====9
0 0
原创粉丝点击