GCD

首先要肯定:一个线程只能执行一个任务,执行完才会执行另外一个任务程序员

先总结一张图网络

同步和异步并发

dispatch_sync 是同步的方式执行任务
dispatch_async 是异步的方式执行任务
同步和异步的区别
同步:在当前线程中执行(不会开辟新线程,是在当前线程执行,通常使用同步执行任务会立马执行,‘写了跟没写同样’)  
异步:在另外一条新的线程中执行(把任务放在主队列里,可是不须要立刻执行)异步

串行队列和并行队列async

串行队列:一个一个执行,就算在异步执行的时候,也只会开辟一条新线程(若是主线程是数字是1,那串行队列只会开辟出一个数字2的线程),而且全部的任务都会在新的线程中执行
dispatch_queue_t  queue = dispatch_queue_create(“label”, DISPATCH_QUEUE_SERIAL);
或者
dispatch_queue_t  queue = dispatch_queue_create(“label”, NULL);  这两种的建立方式是同样的 程序中会常常写成NULL;
spa


并行队列:在异步执行时会开辟不少新的线程,能够同时执行多个任务,顺序是程序员没法控制的
dispatch_queue_t  queue = dispatch_queue_create(“label”, DISPATCH_QUEUE_CONCURRENT);
并发队列的同步执行,不开辟新线程,一步一步执行任务
线程

GCD     主线程
1. 专门在主线程上调度任务
2. 不会开辟新线程,无论同步异步执行,只能在主线程上顺序执行
code

主线程的异步执行任务blog

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self gcdText5];
}

- (void)gcdText5
{
    // 1.得到主线程
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    NSLog(@"1-------");
    
    // 2.异步执行任务
    // 把任务放在主队列里,可是不须要立刻执行
    for (int i = 0; i < 10; i++) {
        NSLog(@"调度前-----");
        // 任务:block
        dispatch_async(queue, ^{
            NSLog(@"%@, %d", [NSThread currentThread], i);
        });
        NSLog(@"睡会");
        [NSThread sleepForTimeInterval:2.0];
    }
    
    NSLog(@"完成");
    
}

这是运行顺序是以下图队列

2016-05-29 17:09:24.945 GCD[6702:82350] 1-------
2016-05-29 17:09:24.946 GCD[6702:82350] 调度前-----
2016-05-29 17:09:24.946 GCD[6702:82350] 睡会
2016-05-29 17:09:26.951 GCD[6702:82350] 调度前-----
2016-05-29 17:09:26.951 GCD[6702:82350] 睡会
2016-05-29 17:09:28.954 GCD[6702:82350] 调度前-----
2016-05-29 17:09:28.954 GCD[6702:82350] 睡会
2016-05-29 17:09:30.959 GCD[6702:82350] 调度前-----
2016-05-29 17:09:30.959 GCD[6702:82350] 睡会
2016-05-29 17:09:32.963 GCD[6702:82350] 调度前-----
2016-05-29 17:09:32.964 GCD[6702:82350] 睡会
2016-05-29 17:09:34.969 GCD[6702:82350] 调度前-----
2016-05-29 17:09:34.969 GCD[6702:82350] 睡会
2016-05-29 17:09:36.971 GCD[6702:82350] 调度前-----
2016-05-29 17:09:36.971 GCD[6702:82350] 睡会
2016-05-29 17:09:38.971 GCD[6702:82350] 调度前-----
2016-05-29 17:09:38.971 GCD[6702:82350] 睡会
2016-05-29 17:09:40.974 GCD[6702:82350] 调度前-----
2016-05-29 17:09:40.974 GCD[6702:82350] 睡会
2016-05-29 17:09:42.977 GCD[6702:82350] 调度前-----
2016-05-29 17:09:42.977 GCD[6702:82350] 睡会
2016-05-29 17:09:44.981 GCD[6702:82350] 完成
2016-05-29 17:09:44.981 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 0
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 1
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 2
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 3
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 4
2016-05-29 17:09:44.982 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 5
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 6
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 7
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 8
2016-05-29 17:09:44.983 GCD[6702:82350] <NSThread: 0x7ffddb501290>{number = 1, name = main}, 9

为何会产生这种效果呢

由于异步执行只是把任务放在队列中,不会立刻执行,由于主队列的特殊性又不能开辟新的线程,因此会等到主线程的任务执行完才会执行队列中的任务 , 如图

此时主线程正在执行gcdText5这个任务,

当gocText5任务执行完成后在执行  绿色的0,1任务

 

主线程的同步执行任务

只须要将代码

 dispatch_async

 

换成

 dispatch_sync

就能够了,这是运行效果回事这样的

这是由于

 同步任务要立刻执行,可是线程没空,线程正在执行gcdText5,须要等gcdText5执行完,可是gcdText5在等这个同步任务执行结束,因此会形成主线程阻塞,产生死锁

全局队列

全局队列和并发队列的区别
 1.全局队列没有名称,并发队列有名称
 2.全局队列,是供全部的应用程序共享
 3.在MRC开发中并发队列须要释放,全局队列不须要管理

 

// 全局队列:是苹果官方提供的,是指上也是并发队列
    /*
     参数:第一个参数,通常写 0 (能够适配iOS 7 & 8)
(优先级)DISPATCH_QUEUE_PRIORITY_HIGH:         QOS_CLASS_USER_INITIATED
   (0) DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT
       DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY
       DISPATCH_QUEUE_PRIORITY_BACKGROUND:   QOS_CLASS_BACKGROUND
          第二个参数:保留参数  0
     **/
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    for (int i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            NSLog(@"%@, %d", [NSThread currentThread], i);
        });
    }

 

调度组

/*
    应用场景
    开发的时候出现多个网络请求(每个网络请求的时间长短不必定),都完成之后,在统一通知用户
    
    例如:下载小说:三国演义 西游记 金x梅
    **/
    
    // 实例化一个调度组
    dispatch_group_t group = dispatch_group_create();
    
    // 队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    // 任务添加到队列
    dispatch_group_async(group, queue, ^{
        NSLog(@"下载小说A%@", [NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下载小说b%@", [NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下载小说x%@", [NSThread currentThread]);
    });
    
    // 得到全部调度组里面的异步任务完成的通知(能够跨队列通讯)
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 在主线程更新UI
        NSLog(@"下载完成,请观看%@", [NSThread currentThread]);
    });

一次性执行   

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self once];
}

#pragma mark - 一次性执行
- (void)once
{
    static dispatch_once_t onceToken;
    
    NSLog(@"%ld", onceToken);
    
    dispatch_once(&onceToken, ^{
        
        NSLog(@"%ld", onceToken);
        NSLog(@"真的只会执行一次么?");
    });
    
    NSLog(@"完成");
}

运行结果

2016-05-30 17:34:57.939 GCD[29725:464402] 0
2016-05-30 17:34:57.940 GCD[29725:464402] 140734769974144
2016-05-30 17:34:57.940 GCD[29725:464402] 真的只会执行一次么?
2016-05-30 17:34:57.940 GCD[29725:464402] 完成
2016-05-30 17:34:59.898 GCD[29725:464402] -1
2016-05-30 17:34:59.898 GCD[29725:464402] 完成
2016-05-30 17:35:00.690 GCD[29725:464402] -1
2016-05-30 17:35:00.690 GCD[29725:464402] 完成
2016-05-30 17:35:01.090 GCD[29725:464402] -1
2016-05-30 17:35:01.091 GCD[29725:464402] 完成
2016-05-30 17:35:02.146 GCD[29725:464402] -1
2016-05-30 17:35:02.147 GCD[29725:464402] 完成
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息