GCD详解

它是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的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效果一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值