6-1 GCD有几种队列

线程和队列

注意:队列是用来存放任务的,队列并不等于线程,队列中存放的任务最后都要由线程来执行
一个一个任务排队就是队列
线程和队列完全就是完全不搭边的两个概念,线程就是你cpu的处理能力,队列就是一个任务容器,cpu从容器中取出任务,然后放到线程去执行 ,他俩之间就这点联系

队列的循环等待问题

嵌套两个同步 串行队列 就会造成 队列的循环等待。造成死锁

GCD:

GCD:其实就是不用我们创建线程池GCD已经帮我们创建好了,他会帮我们创建线程,销毁线程决定着你的代码块将在哪个线程被执行,还根据可用的系统资源对这些线程进行管理

线程数量由谁决定

[由操作系统比如核心数量] 我们的NSOperation 的 maxConcurrentOperationCount 只是可以决定任务的数量

NSThread打印分析

<NSThread: 0x60c000461c40>{number = 3, name = (null)} Thread 3 子线程
<NSThread: 0x60800006dd80>{number = 1, name = main} 主线程 主线程number就是1


如何使用多线程

我们使用多线程的时候 应该首先创建队列 在想队列里面添加任务(同步任务和异步任务)
1.什么是同步?不开启新的线程
dispatch_sync :在当前线程执行

2.什么是异步?开启新的线程
dispatch_async :开启了新的线程

3.如何创建队列?
串行队列(主队列):按照指派的顺序来执行任务,前一个执行完下一个才能执行
dispatch_queue_t chuanxingduilie = dispatch_queue_create("chuanxingduilie", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t mainQueue = dispatch_get_main_queue();

并行队列(全局队列):同时执行多个任务,结束开始的顺序不一定
dispatch_queue_t bingxingduilie = dispatch_queue_create("bingxingduilie", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
主队列 要在主线程中执行

4.什么是任务?
添加进队列里面的
dispatch_sync(syncQueue, ^{
myName = _name;
});
dispatch_sync表示同步。syncQueue 串形队列

5.系统提供的dispatch_get_global_queue 第二个参数可以设置 只能保证任务开始的顺序不能保证任务结束的顺序
DISPATCH_QUEUE_PRIORITY_HIGH Concurrent Dispatch Queue 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT Concurrent Dispatch Queue 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW Concurrent Dispatch Queue 低优先级

6.同步 异步 串形队列 并行队列
组合
同步 不创建新的线程 不管 串形队列 并行队列 都会一个一个执行 同步需要注意线程死锁


1.什么是线程安全?

多线程执行的结果和单线程是一样的 就保证了线程安全
有且只有一个线程写操作 允许同时多个线程读操作
就是我银行卡有2000 那么我存取的时候会把它锁住,保证只有一个对象操作这个数据。
iOS-SDK只提供了非线程安全的数组
iOS中如何保证数组线程安全呢?

///>. 多读单写
dispatch_queue_t syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- (NSString*)name {
    __block NSString *myName;
    dispatch_sync(syncQueue, ^{
        myName = _name;
    });
    return myName;
}

///> 异步障碍任务只会将队列中的任务设置障碍而不会阻碍后面的主线程的代码.
///> 队列中的任务 一个一个执行 不可以同时写
- (void)setName:(NSString*)name {
    dispatch_barrier_async(syncQueue, ^{
        _name = name;
    });
}

GCD其他函数

dispatch_barrier_async:栅[zha]栏函数;队列里面的 前面执行完 才会执行后面的
dispatch_suspend(queue):函数挂起指定的Dispatch Queue
dispatch_resume(queue):函数恢复指定的dispatch Queue

dispatch_after:延迟函数

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"---%@",[NSThread currentThread]);
    });
    // 2s中之后调用run方法
    [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
    // repeats:YES 是否重复
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

dispatch_group:多个处理全部请求结束后想要执行结果处理

    // 创建队列组
    dispatch_group_t group = dispatch_group_create();
    // 创建并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    // 执行队列组任务
    dispatch_group_async(group, queue, ^{
        NSLog(@"队列组 ---1---%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        for (int i = 0; i<10000000; i++) {
        }
        NSLog(@"队列组 ---2---%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"队列组 ---3---%@",[NSThread currentThread]);
    });
    //队列组中的任务执行完毕之后,执行该函数
    dispatch_group_notify(group, queue, ^{
         NSLog(@"队列组 ---notify---%@",[NSThread currentThread]);
    });

dispatch_once:函数是保证在应用程序执行中只执行一次指定处理的API

+ (instancetype)sharedInstance {
    static ClassName *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc]init];
    });
    return sharedInstance;
}

Dispatch Semaphore:可以设置线程数量的函数

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //任务1
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 1");
        sleep(1);
        NSLog(@"complete task 1");
        dispatch_semaphore_signal(semaphore);
    });
    //任务2
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 2");
        sleep(1);
        NSLog(@"complete task 2");
        dispatch_semaphore_signal(semaphore);
    });
    //任务3
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 3");
        sleep(1);
        NSLog(@"complete task 3");
        dispatch_semaphore_signal(semaphore);
    });

dispatch_apply:重复执行

该函数是dispatch_sync函数和Dispatch Group的关联API。按照指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束

    dispatch_queue_t queue111 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_apply(10, queue111, ^(size_t index) {
        NSLog(@"%zu",index);
    });

// GCD定时器

// GCD定时器
static dispatch_source_t _timer;
- (void)startGCDTimer {
    if (_timer) return;
    NSTimeInterval period = 0.05; //设置时间间隔
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0);
    // 事件回调
    dispatch_source_set_event_handler(_timer, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self upDateProgress];
        });
    });
    // 开启定时器
    dispatch_resume(_timer);
    //    关闭定时器
    //    dispatch_source_cancel(_timer);
}

dispatch_barrier_async 异步任务123 执行完执行任务 0 在异步执行456

使用dispatch_barrier_sync此函数创建的任务会首先去查看队列中有没有别的任务要执行,如果有则会等待已有任务执行完毕再执行;同时在此方法后添加的任务必须等到此方法中任务执行后才能执行,利用这个方法可以控制执行顺序

1.   dispatch_group
2.   dispatch_barrier_async   不会阻塞线程。但是我执行完 456才会执行
dispatch_barrier_sync  里面任务同步执行完 再执行后面的 阻塞主线程
如果需要执行10秒 那么会等待10秒
    dispatch_queue_t queue = dispatch_queue_create("com.xxccqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<3; i++) {
            NSLog(@"%zd-download1--%@",i,[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<3; i++) {
            NSLog(@"%zd-download2--%@",i,[NSThread currentThread]);
        }
    });
    //栅栏函数
    dispatch_barrier_async(queue, ^{
        NSLog(@"我是一个栅栏函数");
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<3; i++) {
            NSLog(@"%zd-download3--%@",i,[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<3; i++) {
            NSLog(@"%zd-download4--%@",i,[NSThread currentThread]);
        }
    });
    //通知主线程刷新  
    dispatch_async(dispatch_get_main_queue(), ^{  
        //回调或者说是通知主线程刷新,  
    });
队列的循环等待问题 只有同步 串形
    dispatch_queue_t bingxingduilie = dispatch_queue_create("bingxingduilie", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t chuanxingduilie = dispatch_queue_create("chuanxingduilie", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(chuanxingduilie, ^{
        NSLog(@"2222");
        dispatch_sync(chuanxingduilie, ^{
            NSLog(@"3333");
        });
    });

上面的会造成死锁
但是换成 bingxingduilie  则不会

5秒钟没有执行完执行另外一个函数

- (void)fiveMin:(void (^)(int result))response {
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    __block int count = 0;
    dispatch_group_async(group, queue, ^{
        for (NSInteger i = 0; i < 100000; i++) {

        }
        count = 1;
    });
    /// 可以设置超时参数
    dispatch_time_t time = dispatch_time(0, 0.00001 * NSEC_PER_SEC);
    dispatch_group_wait(group, time);
    
    /// 1秒没有执行完
    if (count != 1) {
        if (response) {
            response(100);
        }
    } else {
        dispatch_group_notify(group, queue, ^{
            if (response) {
                response(1);
            }
        });
    }
}

iOS 底层解读

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容