多线程开发(GCD)

289 阅读3分钟

1、GCD

Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。

GCD好处

* GCD 可用于多核的并行运算;
* GCD 会自动利用更多的 CPU 内核(比如双核、四核);
* GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程);
* 程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码。需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码。

队列和任务

任务通俗点是指需要执行的代码块,队列是指就是排队。他们关系就是代码块排队等着被执行。

同步队列执行和异步执行

同步执行 是指大家都的排在同一个队被执行,只有上个执行完后才能执行下个。异步执行,是指对队中可以同时执行多个任务,不需要等待上个任务就可以执行下个任务,异步有开启多个线程处理任务的能力。

用法

// 队列创建

// 主队列的获取方法
dispatch_queue_t queue = dispatch_get_main_queue();
// 全局并发队列的获取方法
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 串行队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
// 并发队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);

// 任务创建
// 同步执行任务
dispatch_sync(queue, ^{
 // todo
});
// 异步执行任务
dispatch_async(queue, ^{
 // todo
});

线程的使用需要注意死锁等相关问题

其他GCD方法

栅栏方法:dispatch_barrier_async

// 隔离两组并发队列的执行,只有执行了dispatch_barrier_async前加入的任务才会执行接下来的任务
- (void)barrier {
    dispatch_queue_t queue = dispatch_queue_create("com.cnxq.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    });
    dispatch_async(queue, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    dispatch_barrier_async(queue, ^{
        // 追加任务 barrier
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"barrier---%@",[NSThread currentThread]);// 打印当前线程
    });
    
    dispatch_async(queue, ^{
        // 追加任务 3
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    });
    dispatch_async(queue, ^{
        // 追加任务 4
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"4---%@",[NSThread currentThread]);      // 打印当前线程
    });
}

延时执行方法:dispatch_after ,只执行一次:dispatch_once,快速迭代方法:dispatch_apply,快速迭代方法:dispatch_apply

// 2.0f s后执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"after---%@",[NSThread currentThread]);  // 打印当前线程
    });
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 这里只会被执行一次
    });
    
    // block 会类似异步执行,但是会等待所有的执行完毕后才退出循环
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    NSLog(@"egin");
    dispatch_apply(10, queue, ^(size_t index) {
        NSLog(@"%zd---%@",index, [NSThread currentThread]);
    });
    NSLog(@"end");

队列组:dispatch_group,dispatch_group_notify

NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group =  dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("com.cnxq.queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_async(group, queue, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    // 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    dispatch_group_async(group, queue, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步任务 1、任务 2 都执行完毕后,回到主线程执行下边任务
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程

        NSLog(@"group---end");
    });

信号量:dispatch_semaphore,通俗解释将异步执行任务转换为同步执行任务

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int number = 0;
dispatch_async(queue, ^{
	// 追加任务 1
	[NSThread sleepForTimeInterval:2];              // 模拟耗时操作
	NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
	number = 100;
	dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);