美文网首页
GCD(用法一)

GCD(用法一)

作者: gpylove | 来源:发表于2018-11-22 16:26 被阅读1次

    GCD线程通讯:

    在iOS开发过程中,我们一般在主线程里边进行UI刷新。我们通常会把一些耗时的操作放在其他线程,比如说图片下载、文件上传等。而当我们有时候在其他线程完成了耗时操作时,需要回到主线程,那么就用到了线程之间的通讯。已下载图片为例:

    - (void)communication {

        __weak typeof(self) weakSelf = self;

        self.imageView.image= [UIImageimageNamed:@"屏幕快照"];

        dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        dispatch_queue_t mainQueue = dispatch_get_main_queue();

        dispatch_async(globalQueue, ^{

            UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://img95.699pic.com/desgin_photo/40084/3149_detail.jpg"]]];

            dispatch_async(mainQueue, ^{

                weakSelf.imageView.image= image;

            });

        });

    }

    GCD单例:dispatch_once

    void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);

    //第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词。

    //第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全的。

    我们在创建单例、或者有整个程序运行过程中只执行一次的代码时,我们就用到了 dispatch_once 函数。它能保证某段代码在程序运行过程中只被执行一次,并且即使在多线程的环境下,它也可以保证线程安全。单例为例:

    + (instancetype)sharedInstance {

        static GCDTimer *manager = nil;

        static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            manager = [[GCDTimer alloc] init];

        });

        returnmanager;

    }

     GCD 延时执行:dispatch_after

    当我们需要延迟执行一段代码时,就需要用到dispatch_after方法,dispatch_after是延迟将任务提交到队列中,不要理解成延迟执行任务。

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

        dispatch_after(time, dispatch_get_main_queue(), ^{

            NSLog(@"after");

        });

    GCD 快速迭代:dispatch_apply

    dispatch_apply按照指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束。可以快速完成对顺序没有要求的集合进行遍历。如果是在串行队列中使用此函数,那么就和 for 循环一样,按顺序同步执行。可这样就体现不出快速迭代的意义了。我们可以利用并发队列进行异步执行。比如说遍历 0~5 这6个数字,for 循环的做法是每次取出一个元素,逐个遍历。此函数可以在多个线程中同时(异步)遍历多个数字。提升速度,所以建议在异步执行中使用此函数。

    - (void)apply {

        NSLog(@"begin");

        NSLog(@"%@",[NSThread currentThread]);

        dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) {

            NSLog(@"%@我开始执行 %zu times",[NSThreadcurrentThread],i+1);

        });

        NSLog(@"end");

    }

     GCD 栅栏:dispatch_barrier

    一个dispatch_barrier允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier,他会延迟执行barrier的任务,等待所有在barrier之前提交的任务执行结束。 这时barrier的任务自己开始执行。 之后队列继续正常的执行操作。

    - (void)barrier

    {

        NSLog(@"begin");

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

        dispatch_async(queue, ^{

            NSLog(@"----1-----%@", [NSThread currentThread]);

        });

        dispatch_async(queue, ^{

            NSLog(@"----2-----%@", [NSThread currentThread]);

        });

        dispatch_async(queue, ^{

            NSLog(@"----3-----%@", [NSThread currentThread]);

        });

        dispatch_barrier_async(queue, ^{

            NSLog(@"----barrier-----%@", [NSThread currentThread]);

        });

        dispatch_async(queue, ^{

            NSLog(@"----4-----%@", [NSThread currentThread]);

        });

        dispatch_async(queue, ^{

            NSLog(@"----5-----%@", [NSThread currentThread]);

        });

        dispatch_async(queue, ^{

            NSLog(@"----6-----%@", [NSThread currentThread]);

        });

        NSLog(@"end");

    }

    注意:这里指定的并发队列应该是自己通过dispatch_queue_create函数创建的。如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_async函数。

    区别:dispatch_barrier_sync和dispatch_barrier_async

    1、dispatch_barrier_sync将自己的任务插入到队列的时候,需要等待自己的任务结束之后才会继续插入被写在它后面的任务,然后执行它们。

    2、dispatch_barrier_async将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。

    相关文章

      网友评论

          本文标题:GCD(用法一)

          本文链接:https://www.haomeiwen.com/subject/chvkqqtx.html