多线程工具之GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。

使用GCD,不需要管理线程,线程管理完全托管给GCD。

用纯c写的,一般用block来描述

首先要了解同步和异步,串行和并行的区别:

同步:a请求b任务,只有b任务给予a反馈,a才能继续执行

异步:a请求b任务时,a无需等待b回应就可以继续执行其他操作

串行:一个任务完成下一个任务菜可能开始

并行:在同一时刻,两个任务开始执行,但互不干扰

1.dispatch queue

dispatch queue分成以下三种:

1)运行在主线程的Main queue,通过dispatch_get_main_queue获取。

2)并行队列global dispatch queue(可以多个线程并行,任务可以同时执行),通过dispatch_get_global_queue获取,由系统创建三个不同优先级的dispatch queue。并行队列的执行顺序与其加入队列的顺序相同。

3)串行队列serial queues(所有线程串行,或者只有一个线程,任务依次执行 )一般用于按顺序同步访问,可创建任意数量的串行队列,各个串行队列之间是并发的。

当想要任务按照某一个特定的顺序执行时,串行队列是很有用的。串行队列在同一个时间只执行一个任务。我们可以使用串行队列代替锁去保护共享的数据。和锁不同,一个串行队列可以保证任务在一个可预知的顺序下执行。

serial queues通过dispatch_queue_create创建,可以使用函数dispatch_retain和dispatch_release去增加或者减少引用计数。


//创建串行的队列

//第一个参数表示queue的名字,,,第二个参数表示queue的类型
    dispatch_queue_t queue_1 = dispatch_queue_create("queue.1", DISPATCH_QUEUE_SERIAL);


//创建并行的队列

dispatch_queue_t queue_2 = dispatch_queue_create("queue.2", DISPATCH_QUEUE_CONCURRENT);


//获取全局并发的queue(属于并行队列)
    //第一个参数表示优先级,,,第二个参数暂时没用

dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);


//获取管理主线程的queue(属于串行队列)

//提交给main queue的任务可能不会立马被执行,而是在主线程的Run Loop检测到有dispatch 提交过来的任务时才会执行

dispatch_queue_t main_queue = dispatch_get_main_queue();

 

2.提交任务

分为两种:同步提交和异步提交

两个参数:

。第一个参数表示提交到的queue

。第二个参数表示任务详情,这里用block的方式描述一个任务,原因很简单,Block也是 纯C实现的,而平时使用的Invocation或者target+selector方式都是面向对象的。

 


//获取全局并发的queue
    dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//1.同步提交

//如果使用同步请求方式,会造成卡死当前线程的后果。
    //同步提交任务后,先执行完block,然后dispatch_sync()返回
    dispatch_sync(global_queue, ^{
        NSLog(@"do something");
    });
    NSLog(@"OK");

//2.异步提交

//异步提交任务后,dispatch_async()函数直接返回,无需等待block执行结束
    dispatch_async(global_queue, ^{
        NSLog(@"do something.....");
    });

NSLog(@"OK.....");

//3.同步提交多次任务

dispatch_queue_t queue_1 = dispatch_queue_create("queue.1", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue_2 = dispatch_queue_create("queue.2", DISPATCH_QUEUE_CONCURRENT);
   
    //任务数量
    size_t count = 10;
   
    //同步提交多次任务
    //三个参数分别是:任务数,目标queue,任务描述
    //如果目标queue是串行的,那么任务会依次执行,如果queue是并行的,那么任务会并发的执行,打印的顺序就会被打乱
    dispatch_apply(count, queue_2, ^(size_t i) {
        NSLog(@"%zu",i);
    });
    NSLog(@"---OK---");

//比较同步提交多个任务和遍历数组哪个快   (在不关心数组顺序的前提下)

//遍历数组
    NSMutableArray* array = [[NSMutableArray alloc]initWithCapacity:1000];
   
    for (int i =0; i<1000; i++) {
        [array addObject:[NSString stringWithFormat:@"%d",i]];
       
    }

NSLog(@"start forin");

//数组遍历

for (NSString* a in array) {
        NSLog(@"--%@",a);
    }

NSLog(@"fisined forin");

NSLog(@"start apply");

//同步提交多个任务

dispatch_apply(array.count, queue_2, ^(size_t i) {
        NSLog(@"%@",array[i]);
    });

NSLog(@"fisined apply");

 

3.死锁

同步提交在某种情况下会造成死锁,即卡死。


//主线程(属于串行队列)死锁

//不会打印出任何东西

dispatch_queue_t main_queue = dispatch_get_main_queue();

//同步执行

dispatch_sync(main_queue, ^{
        NSLog(@"-----");
    });

NSLog(@"OK");

程序默认是从上往下执行的,但是程序走到dispatch_sync时,又会先走block再返回到dispatch_sync,这样就会照成冲突,形成死锁


    //串行队列
    dispatch_queue_t queue_1 = dispatch_queue_create("queue.1", DISPATCH_QUEUE_SERIAL);
    //异步提交
    dispatch_async(queue_1, ^{
      
        //不会被打印
        //同步提交
        dispatch_sync(queue_1, ^{
            NSLog(@"bbb");
        });
        NSLog(@"ccccc");
       
    });

NSLog(@"aaaa");

死锁解决方案:串行队列异步执行,并行队列同步执行。

       串行队列中 ,同步提交任务给本身队列,就会出现死锁。要想不出现死锁就把串行队列改为并行队列,或把同步提交任务改为异步提交。

       

4. Dispatch Group

什么是dispatch group,就像我们在NSOperation中添加依赖一样,如果我们一个任务需要等待其他一些任务完成才能执行时

4.1 提交任务

分为两步:

1.创建group

2.提交任务,并且把任务添加到group中


//1.创建group

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)


//2.提交一个任务给global_queue ,并且添加到group中

/ / global_queue并非是一个queue,但group必须是同一个

/ / group只有异步提交,没有同步提交

dispatch_group_async(group, global_queue, ^{
       
        usleep(10000);
        NSLog(@"买锅");
       
    });
   
    dispatch_group_async(group, global_queue, ^{
        usleep(10000);
        NSLog(@"买菜");
       
    });
   
    dispatch_group_async(group, global_queue, ^{
        usleep(10000);
        NSLog(@"买饮料");

});


//3.异步提交终极任务给queue ,main_queue

//终极任务就相当于operation1依赖于Operation2一样,只是operation1不能和之前提交任务一样,而是需要终极任务dispatch_group_notify提交

//异步提交 不阻塞当前线程

//要想阻塞当前线程,一直等待group所有任务结束,需要用到dispatch_group_wait

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"吃火锅");
    });

//创建dispatch time

//可以自定义超时时间,只等待一定的时间

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(200 * NSEC_PER_SEC));

//4.自定义超时时间

//设置超时时间,阻塞当前线程

dispatch_group_wait(group, time);

//买饮料的时间过长,已经超过了等待的时间,所以很难再执行

NSLog(@"....");

NSLog(@"看电视");

时间: 2024-11-06 09:28:34

多线程工具之GCD的相关文章

多线程——NSThread、GCD、NSOperation

1.前言: 一个应用程序就是一个进程,一个进程至少包含一个线程,程序启动会自动创建一个主线程,负责UI界面的现实和控件事件的监控.多线程可以更充分的利用系统CPU资源,一定程度上提升程序的性能.1个进程可以开启多条线程,每条线程可以并行(同时)执行不同的任务.在一个线程内可以包含多个事物(要干的活),在线程内依据先进先出的特性串行执行…… 2.NSThread - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"main thread is %@

多线程编程4 - GCD

一.简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决方案.GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器.GCD是Grand Central Dispatch的简称,它是基于C语言的.如果使用GCD,完全由系统管理线程,我们不需要编写线程代码.只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue).GCD会负责创建线程和调度你的任务,系统直接提供线程管理 二.调度队列(dispath qu

iOS多线程开发之GCD(下篇)

上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题.有兴趣的朋友可以回顾<iOS多线程开发之GCD(上篇)>和<iOS多线程开发之GCD(中篇)>. 言归正传,我们首先来回顾下死锁,所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源(如数据源,内存等,变量不是资源)而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去. 死锁形成的原因: 系统资源不足 进程(线程)推进的顺序不恰当: 资源分配不当 死锁形成的条件:

iOS开发多线程网络———多线程概念及GCD

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(htt

多线程开发之三 GCD

NSThread.NSOperation.GCD 总结: 无论使用哪种方法进行多线程开发,每个线程启动后并不一定立即执行相应的操作,具体什么时候由系统调度(CPU 空闲时就会执行) 更新 UI 应该在主线程(UI 线程)中进行,并且推荐使用同步调用,常用的方法如下: - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelec

学习IOS开发网络多线程篇--NSThread/GCD/

NSThread:利用NSThread创建和启用一个线程 1. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];,调用后调用[thread start]; 2. 创建线程后自动启动线程 ,[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil]; 3. 隐式创建

猫猫学iOS(五十二)多线程网络之GCD下单例设计模式

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 单例模式 1:单例模式的作用 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问 从而方便地控制了实例个数,并节约系统资源 单例模式的使用场合 在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次) 简单来说,就是我弄了一个工具类,他就有一份,比如我设计了一个音乐播放器NYPlayer,这个播放器类我

iOS多线程开发之GCD 用法入门

我们知道,在iOS中进行多线程编程,主要有三种方式:[NSThread].[NSOperation]和[GCD].其中又以[GCD]为苹果官方最为推荐.本文将利用一个简单的demo,简述GCD的用法入门,以及本人对GCD的一点肤浅理解和学习心得. 先把参考文章列出: http://www.cnblogs.com/kenshincui/p/3983982.html http://www.cnblogs.com/sunfrog/p/3305614.html http://mobile.51cto.c

iOS开发多线程篇 05 —GCD介绍

iOS开发多线程篇—GCD介绍 一.简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核.四核) GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 3.提示 (1)GCD存在于libdispatch.dylib这个库中