GCD(用法一)

2018-11-22  本文已影响1人  gpylove

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将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。

上一篇下一篇

猜你喜欢

热点阅读