GCD详解

来源:互联网 发布:如何购买网络域名 编辑:程序博客网 时间:2024/05/20 04:29

它是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程)。


一、队列

队列:用于存放任务。一共有两种队列, 串行队列 和 并行队列

 同步执行异步执行串行队列当前线程,一个一个执行其他线程,一个一个执行并行队列当前线程,一个一个执行开很多线程,一起执行

主队列

dispatch_queue_t queue = dispatch_get_main_queue();
自己创建的队列

//串行队列dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL);dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);//并行队列dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT);
全局并行队列:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

二、同步异步

1、同步

 dispatch_sync(<#queue#>, ^{      //code here      NSLog(@"%@", [NSThread currentThread]);  });

//在main线程使用“同步”方法提交Block,必定会死锁。
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"I am block...");
});

2、异步

 dispatch_async(<#queue#>, ^{      //code here      NSLog(@"%@", [NSThread currentThread]);  });2、异步


三、队列组

队列组可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。

//1.创建队列组dispatch_group_t group = dispatch_group_create();//2.创建队列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//3.多次使用队列组的方法执行任务, 只有异步方法//3.1.执行3次循环dispatch_group_async(group, queue, ^{    for (NSInteger i = 0; i < 3; i++) {        NSLog(@"group-01 - %@", [NSThread currentThread]);    }});//3.2.主队列执行8次循环dispatch_group_async(group, dispatch_get_main_queue(), ^{    for (NSInteger i = 0; i < 8; i++) {        NSLog(@"group-02 - %@", [NSThread currentThread]);    }});//3.3.执行5次循环dispatch_group_async(group, queue, ^{    for (NSInteger i = 0; i < 5; i++) {        NSLog(@"group-03 - %@", [NSThread currentThread]);    }});//4.都完成后会自动通知dispatch_group_notify(group, dispatch_get_main_queue(), ^{    NSLog(@"完成 - %@", [NSThread currentThread]);});


四、其他方法

1、dispatch_once

1
2
3
4
5
//静态变量,保证只有一份实例,才能确保只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
   //单例代码 
});


2、dispatch_after

dispatch_after只是延时提交block,并不是延时后立即执行

//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_CONCURRENT);
//立即打印一条信息        
NSLog(@"Begin add block...");        
//提交一个block
dispatch_async(queue, ^{
    //Sleep 10秒
    [NSThread sleepForTimeInterval:10];
    NSLog(@"First block done...");
});        
//5 秒以后提交block
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
    NSLog(@"After...");
});

结果如下:

1
2
3
2015-03-31 20:57:27.122 GCDTest[45633:1812016] Begin add block...
2015-03-31 20:57:37.127 GCDTest[45633:1812041] First block done...
2015-03-31 20:57:37.127 GCDTest[45633:1812041] After...
After后打印的原因是after的block后提交的,而队列是串行队列,Sleep 10秒,即把线程阻塞了10s,执行完First后,才去执行After。


3、dispatch_suspend

并不会立即暂停正在运行的block,而是在当前block执行完成后,暂停后续的block执行。

dispatch_suspend(queue);


4、dispatch_resume

恢复队列上的任务

dispatch_resume(queue);


5、dispatch_apply

作用是在一个队列(串行或并行)上“运行”多次block,其实就是简化了用循环去向队列依次添加block任务。

1
2
3
4
5
6
7
8
//创建异步串行队列
dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);
//运行block3次
dispatch_apply(3, queue, ^(size_t i) {
    NSLog(@"apply loop: %zu", i);
});
//打印信息
NSLog(@"After apply");

运行的结果是:

1
2
3
4
2015-04-01 00:55:40.854 GCDTest[47402:1893289] apply loop: 0
2015-04-01 00:55:40.856 GCDTest[47402:1893289] apply loop: 1
2015-04-01 00:55:40.856 GCDTest[47402:1893289] apply loop: 2
2015-04-01 00:55:40.856 GCDTest[47402:1893289] After apply

看,明明是提交到异步的队列去运行,但是“After apply”居然在apply后打印,也就是说,dispatch_apply将外面的线程(main线程)“阻塞”了!
查看官方文档,dispatch_apply确实会“等待”其所有的循环运行完毕才往下执行。


一定要避免dispatch_apply的嵌套调用,否则会导致死锁


6、dispatch_barrier_sync

7、dispatch_barrier_async

dispatch_barrier_async的作用就是向某个队列插入一个block,当目前正在执行的block运行完成后,阻塞这个block后面添加的block,只运行这个block直到完成,然后再继续后续的任务。

dispatchbarrier\(a)sync只在自己创建的并发队列上有效,在全局(Global)并发队列、串行队列上,效果跟dispatch_(a)sync效果一样。

0 0
原创粉丝点击