宽容他人,放过自己。

GCD(Grand Central Dispatch)使用

Posted on By anchoriteFili

GCD 深入理解(一)
GCD 深入理解(二)

Grand Central Dispatch简称(GCD)是苹果公司开发的技术。 GCD数据函数级的多线程,性能更高,功能也更加强大。

GCD核心概念:具有一定功能的代码段。一般是一个block或者函数。

分发队列:GCD以队列的方式进行工作,FIFO:first in first out。 GCD会根据分发队列的类型创建合适数量的线程执行队列中的任务。

dispatch queue分为两种:

SerialQueue:一次只执行一个任务。Serial(连续的) queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue是,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。SerialQueue能实现线程同步。 Concurrent:可以并发地执行多个任务,但是遵守FIFO。

GCD方法:

dispatch_async()  //向队列中添加任务,任务会排队执行

dispatch_after()   //向队列中添加任务,任务不但会排队,还会过一段时间以后

在执行,这个时间自己设定。

dispatch_apply()  //向队列中添加任务,任务会重复执行n次--次数自己设定;

dispatch_group_async()  //将任务添加到队列中,并添加分组标记

dispatch_group_notify()  //将任务添加到队列中,当某个分组的所有任务都执行

完成后,此任务才会执行。

dispatch_barrier_async()  //将任务添加到队列中,此任务执行的时候,其他任务停止执行。

dispatch_once()  //任务添加到队列中,但恩物在程序执行的过程中,只执行一次。

dispatch_sync()  //将任务添加到队列中,block不执行完,下面代码不会执行。

dispatch_async_f()  //将任务添加到队列中,任务是函数非block。

注:gcd不支持结束子线程操作

线程间通信分为两种:

主线程进入子线程(前面的方法都是)。 子线程回到主线程方法有两种:

GCD:dispatch_get_main_queue()
NSObject:- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

线程互斥

线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它型。 互斥无法限制访问者对资源的访问顺序,即访问是无序的,因此需要加上互斥锁来进行顺序访问, 最具有代表性的就是买票系统! NSLock类能协助完成互斥操作。 多线程间相互通讯

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //子线程完成操作
        UIImage *image = nil;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //回到主线程
        });
        
        /**
         //直接将得到的数据传到下面的方法中,在主线程中对得到对象进行处理
         [self performSelectorOnMainThread:@selector(heheh:) withObject:image waitUntilDone:NO];
         
         [self performSelector:@selector(heheh:)  onThread:[NSThread mainThread] withObject:image waitUntilDone:YES modes:nil];
         */
    });
//    GCD:Grand Central Dispatch
    /*
     同步线程也并发线程都各自包括两种,一种是系统提供的线程,另外一种 就是自己创造的线程
     */
    
//    4.1同步线程
//    4.1.1获取同步队列 获取系统提供的主队列
    /*
     系统给每个应用程序提供了三个concurrent dispatch queue。
     这三个并发调度队列是全局的,它们只有优先级的不同。
     因为是全局的,我们不需要去创建。我们只需要通过使用该函数
     dispath_get_global_queue去得到队列
     系统默认就有一个串行队列main_queue
     dispatch_queue_t global = dispatch_get_global_queue
     (DISPATCH_QUEUE_PREIORITY_DEFAULT,0);
     dispatch_queue_t main = dispatch_get_main_queue();
     */
//    dispatch_queue_t queue = dispatch_get_main_queue();
////    dispatch_async是在另外一个线程中处理这些操作,然后再通知
////    主线程更新界面
//    dispatch_async(queue, ^{
//        NSLog(@"%@--%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
    
    
//    4.1.2 创建自定义同步队列
    dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.150303", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSLog(@"%@---%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    
//    4.2 并发队列
//    4.2.1 获取系统提供的并发队列,所有的线程同时运行

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i < 100; i ++) {
            NSLog(@"1");
            sleep(1);
        }
    });
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i < 100; i ++) {
            NSLog(@"2");
            sleep(1);
        }
    });
    
    
//    4.2.2 创建自定义并发队列
    dispatch_async(dispatch_queue_create("com.lanou3g.150303.concurrent", DISPATCH_QUEUE_CONCURRENT), ^{
        NSLog(@"hahah");
    });
    
//    dispatch_after的使用
//    方法在time时间过去之后开始执行
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        NSLog(@"hahaha");
    });

//    dispatch_apply重复执行
//    第一个参数表示重复执行任务次数
//    Parameter name omitted 参数名字缺失,添加block参数
    dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t t) {
        NSLog(@"hahah");
    });
    
    
//    dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他他的操作
    
    dispatch_group_async(dispatch_group_create(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"hahha");
    });
    
    dispatch_group_async(dispatch_group_create(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"heheh");
    });
    
    dispatch_group_async(dispatch_group_create(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"heihei");
    });
    
//    上边的任务都完成了再执行这个通知任务
    dispatch_group_notify(dispatch_group_create(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"oheheeh");
    });
    
//   dispatch_barrier_async的使用
    dispatch_async(dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT), ^{
        NSLog(@"hahahh");
    });
    
    dispatch_async(dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT), ^{
        NSLog(@"hahahh");
    });
    
    dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"hljljl");
    });
    
    dispatch_async(dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT), ^{
        NSLog(@"hahahh");
    });
    
//    dispatch_once只执行一次
    
//    dispatch_sync是同步分发,这个任务没有完成下边的语句不执行
//    dispatch_async是异步分发,任务没哟完成就克执行下边的语句
//    后边加_f的是函数形式
    dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), "hehe", func);