GCD

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

先总结一张图

同步和异步

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

串行队列和并行队列

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


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

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

主线程的异步执行任务

- (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] 完成

 

posted @ 2016-05-29 17:24  唐宋元明清。  阅读(198)  评论(0编辑  收藏  举报