GCD慢慢整理

/**
 凡是函数名中带有create\copy\new\retain等字眼, 都应该在不需要使用这个数据的时候进行release
 GCD的数据类型在ARC环境下不需要再做release
 CF(Core Foundation)的数据类型在ARC\MRC环境下都需要再做release
 */

1. 队列类型

串行队列:一次只能处理一个任务。(FIFO)一行代码执行完才能执行下一行代码。
并行队列:可以同时处理多个任务。

串行队列


// 第一个参数:队列名随便写,方便调试区别队列
// 第二个参数:一般用NULL(也就是DISPATCH_QUEUE_SERIAL)
/**
#define DISPATCH_QUEUE_SERIAL 
#define DISPATCH_QUEUE_CONCURRENT

DISPATCH_QUEUE_SERIAL
串行队列,遵循先进先出原则

DISPATCH_QUEUE_CONCURRENT
这个比较特殊,创建的是自定义并行队列
*/
dispatch_queue_t queue = dispatch_queue_create("队列名方便调试区别", NULL);

主队列(也是串行队列的一种)

// (添加到主队列中的任务,都会自动放到主线程中去执行。)
// 主队列一般运行一些需要与主线程同步的一些短时任务。
dispatch_queue_t queue = dispatch_get_main_queue();

并发队列(全局队列)

在不得以的情况下可以用dispatch_queue_create创建(串行队列有介绍),但一般我们都要用系统预定义的并行队列。

 // 第一个参数是优先级:一般用DISPATCH_QUEUE_PRIORITY_DEFAULT
/**
#define DISPATCH_QUEUE_PRIORITY_HIGH        2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT     0
#define DISPATCH_QUEUE_PRIORITY_LOW         (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND  INT16_MIN
*/
// 第二个参数留着将来可能有用,默认为0
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  

获取当前队列

// 如果在队列执行任务中调用,返回执行此任务的队列;如果在主线程中调用,将返回主队列;如果在一般线程(非主线程线程非队列执行任务)中调用,返回全局队列。
  dispatch_queue_t queue = dispatch_get_current_queue();

2. 线程同步与异步

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。

举个例子 打电话时同步 发消息是异步

线程与队列组合6种(2 X 3 = 6)(李明杰老师的视频整理的)

dispatch_sync (同步,不具备开启线程的能力)

/**
 *  sync -- 串行队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 */
- (void)syncSerialQueue
{
    // 创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);

    // 将 任务 添加到 串行队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}
/**
 *  sync -- 主队列(不能用---会卡死)
 */
- (void)syncMainQueue
{
    NSLog(@"syncMainQueue----begin--");

    // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
    dispatch_queue_t queue = dispatch_get_main_queue();

    // 2.添加 任务 到主队列中 异步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });

    NSLog(@"syncMainQueue----end--");
}
// 主队列任务队列:->syncMainQueue()->dispatch_sync(queue, ^{})
// 但是实际上是应该执行dispatch_sync(queue, ^{}),陷入死循环
/**
 *  sync -- 并发队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 *  并发队列失去了并发的功能
 */
- (void)syncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 将 任务 添加到 全局并发队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}

dispatch_async(异步,具备开启线程的能力)

/**
 *  sync -- 并发队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 *  并发队列失去了并发的功能
 */
- (void)syncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 将 任务 添加到 全局并发队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}
/**
 *  sync -- 并发队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 *  并发队列失去了并发的功能
 */
- (void)syncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 将 任务 添加到 全局并发队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}
/**
 *  async -- 并发队列(最常用)
 *  会不会创建线程:会,一般同时开多条
 *  任务的执行方式:并发执行
 */
- (void)asyncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 将 任务 添加 全局队列 中去 异步 执行
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}

3. 队列组(dispatch_group_async)

可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。

dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:1]; 
        NSLog(@"group1");   
    });

    dispatch_group_async(group, queue, ^{ 
        [NSThread sleepForTimeInterval:2];  
        NSLog(@"group2");    
    });

    dispatch_group_async(group, queue, ^{  
        [NSThread sleepForTimeInterval:3];
        NSLog(@"group3");    
    }); 

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{     
        NSLog(@"update UI");   
    });

4. 其它使用

线程通信

// 一般异步并行下载图片,然后到主线程刷新界面
 dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    dispatch_async(globalQueue, ^{
        NSLog(@"donwload---%@", [NSThread currentThread]);
        // 1.子线程下载图片

        // 2.回到主线程设置图片
        dispatch_async(mainQueue, ^{
            NSLog(@"setting---%@ %@", [NSThread currentThread], image);
        });
    });

单例实现

 static NSObject *object = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        object = [[NSObject alloc] init];
    });

延时实现

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         NSLog(@"[%s]%d", __func__, __LINE__);
    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值