iOS进阶之路

iOS多线程GCD使用方式

2018-07-18  本文已影响13人  wuyukobe

一、基本介绍

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。

GCD是一个替代诸如NSThread等技术的很高效和强大的技术。GCD完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题。GCD的工作原理是让一个程序,根据可用的处理资源,安排他们在任何可用的处理器核心上平行排队执行特定的任务。这个任务可以是一个功能或者一个程序段。

GCD中的一个任务可被用于创造一个被放置于队列的工作项目或者事件源。如果一个任务被分配到一个事件源,那么一个由功能或者程序块组成的工作单元会被放置于一个适当的队列中。苹果公司认为GCD相比于普通的一个接一个的执行任务的方式更为有效率。

使用GCD 有以下好处:

二、使用方式

GCD的使用需要任务和队列的相互配合:

任务:就是执行GCD中放在 block 中的代码块。执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。

//同步执行
dispatch_sync(queue, ^{
   //添加执行任务
});
//异步执行
dispatch_async(queue, ^{
   //添加执行任务
});

其中的queue就是我们所需要创建的执行队列。

队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。在 GCD 中有两种队列:串行队列并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。

//创建串行队列
dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);
//创建主队列
dispatch_queue_t queue = dispatch_get_main_queue();

其中主队列是GCD提供的一种特殊的串行队列。

//创建并发队列
dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);
//创建全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

其中全局并发队列是GCD提供的一种特殊的并发队列。

下面介绍一下GCD任务和队列的组合使用方式:

1、同步执行 + 并发队列
//1.同步执行 + 并发队列
- (instancetype)initSyncAndConcurrentDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"SyncAndConcurrent---begin");
        
        dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);//创建并发队列
        dispatch_sync(queue, ^{//同步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_sync(queue, ^{//同步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_sync(queue, ^{//同步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"3---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        NSLog(@"SyncAndConcurrent---end");
    }
    return self;
}

输出结果:

2018-07-18 14:06:25.808498+0800 GCD[3487:140302] currentThread---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:25.808716+0800 GCD[3487:140302] SyncAndConcurrent---begin
2018-07-18 14:06:27.810127+0800 GCD[3487:140302] 1---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:29.811518+0800 GCD[3487:140302] 1---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:31.812374+0800 GCD[3487:140302] 2---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:33.812720+0800 GCD[3487:140302] 2---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:35.813879+0800 GCD[3487:140302] 3---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:37.814369+0800 GCD[3487:140302] 3---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:06:37.814666+0800 GCD[3487:140302] SyncAndConcurrent---end
2、异步执行 + 并发队列
//2.异步执行 + 并发队列
- (instancetype)initAsyncAndConcurrentDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"AsyncAndConcurrent---begin");
        
        dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);//创建并发队列
        dispatch_async(queue, ^{//异步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{//异步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{//异步执行
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"3---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        NSLog(@"AsyncAndConcurrent---end");
    }
    return self;
}

输出结果:

2018-07-18 14:13:36.852829+0800 GCD[3487:140302] currentThread---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:13:36.853047+0800 GCD[3487:140302] AsyncAndConcurrent---begin
2018-07-18 14:13:36.853189+0800 GCD[3487:140302] AsyncAndConcurrent---end
2018-07-18 14:13:38.854025+0800 GCD[3487:140559] 2---<NSThread: 0x60400027cc40>{number = 4, name = (null)}
2018-07-18 14:13:38.854027+0800 GCD[3487:145869] 1---<NSThread: 0x600000462780>{number = 3, name = (null)}
2018-07-18 14:13:38.854025+0800 GCD[3487:145877] 3---<NSThread: 0x604000277c00>{number = 5, name = (null)}
2018-07-18 14:13:40.858188+0800 GCD[3487:145869] 1---<NSThread: 0x600000462780>{number = 3, name = (null)}
2018-07-18 14:13:40.858188+0800 GCD[3487:140559] 2---<NSThread: 0x60400027cc40>{number = 4, name = (null)}
2018-07-18 14:13:40.858288+0800 GCD[3487:145877] 3---<NSThread: 0x604000277c00>{number = 5, name = (null)}
3、同步执行 + 串行队列
//3.同步执行 + 串行队列
- (instancetype)initSyncAndSerialDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"SyncAndSerial---begin");
        
        dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);//创建串行队列
        dispatch_sync(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];           //模拟耗时操作
                NSLog(@"1---%@",[NSThread currentThread]);   //打印当前线程
            }
        });
        dispatch_sync(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];           //模拟耗时操作
                NSLog(@"2---%@",[NSThread currentThread]);   //打印当前线程
            }
        });
        dispatch_sync(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];           //模拟耗时操作
                NSLog(@"3---%@",[NSThread currentThread]);   //打印当前线程
            }
        });
        NSLog(@"SyncAndSerial---end");
    }
    return self;
}

输出结果:

2018-07-18 14:18:52.586924+0800 GCD[3487:140302] currentThread---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:18:52.587135+0800 GCD[3487:140302] SyncAndSerial---begin
2018-07-18 14:18:54.587815+0800 GCD[3487:140302] 1---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:18:56.588782+0800 GCD[3487:140302] 1---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:18:58.590248+0800 GCD[3487:140302] 2---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:19:00.591183+0800 GCD[3487:140302] 2---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:19:02.591603+0800 GCD[3487:140302] 3---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:19:04.593199+0800 GCD[3487:140302] 3---<NSThread: 0x604000065440>{number = 1, name = main}
2018-07-18 14:19:04.593466+0800 GCD[3487:140302] SyncAndSerial---end
4、异步执行 + 串行队列
//4.异步执行 + 串行队列
- (instancetype)initAsyncAndSerialDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"AsyncAndSerial---begin");
        
        dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);//创建串行队列
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"3---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        NSLog(@"AsyncAndSerial---end");
    }
    return self;
}

输出结果:

2018-07-18 14:25:13.368635+0800 GCD[3787:154025] currentThread---<NSThread: 0x604000066400>{number = 1, name = main}
2018-07-18 14:25:13.368890+0800 GCD[3787:154025] AsyncAndSerial---begin
2018-07-18 14:25:13.369052+0800 GCD[3787:154025] AsyncAndSerial---end
2018-07-18 14:25:15.373476+0800 GCD[3787:154089] 1---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
2018-07-18 14:25:17.377079+0800 GCD[3787:154089] 1---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
2018-07-18 14:25:19.381357+0800 GCD[3787:154089] 2---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
2018-07-18 14:25:21.382271+0800 GCD[3787:154089] 2---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
2018-07-18 14:25:23.384662+0800 GCD[3787:154089] 3---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
2018-07-18 14:25:25.386662+0800 GCD[3787:154089] 3---<NSThread: 0x6000002709c0>{number = 3, name = (null)}
5、同步执行 + 主队列(会造成死锁)
//5.同步执行 + 主队列(会造成死锁)
- (instancetype)initSyncAndMainDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"SyncAndMain---begin");
        
        dispatch_queue_t queue = dispatch_get_main_queue();
        dispatch_sync(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时操作
                NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        NSLog(@"SyncAndMain---end");
    }
    return self;
}

输出结果:

2018-07-18 14:31:31.002501+0800 GCD[3787:154025] currentThread---<NSThread: 0x604000066400>{number = 1, name = main}
2018-07-18 14:31:31.002743+0800 GCD[3787:154025] SyncAndMain---begin

由此可以看出:

解决死锁的办法:把需要在主队列中同步执行的任务放到其他线程中去。
//同步执行 + 主队列(解决死锁调用方法)
- (instancetype)initSyncAndMainDispatchResolve {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"SyncAndMain---begin");
        //创建其他线程中调用同步执行 + 主队列
        [NSThread detachNewThreadSelector:@selector(SyncMain) toTarget:self withObject:nil];
    }
    return self;
}

- (void)SyncMain {
    NSLog(@"currentThread 4---%@",[NSThread currentThread]);//打印当前线程
    NSLog(@"SyncAndMain 4---begin");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];            //模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
        }
    });
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];            //模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
        }
    });
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];            //模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
        }
    });
    NSLog(@"SyncAndMain---end");
}

输出结果:

2018-07-18 14:38:07.108703+0800 GCD[4000:163392] currentThread---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:07.108999+0800 GCD[4000:163392] SyncAndMain---begin
2018-07-18 14:38:07.110803+0800 GCD[4000:164570] currentThread 4---<NSThread: 0x600000468240>{number = 3, name = (null)}
2018-07-18 14:38:07.111920+0800 GCD[4000:164570] SyncAndMain 4---begin
2018-07-18 14:38:09.114080+0800 GCD[4000:163392] 1---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:11.115053+0800 GCD[4000:163392] 1---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:13.116707+0800 GCD[4000:163392] 2---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:15.117198+0800 GCD[4000:163392] 2---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:17.118623+0800 GCD[4000:163392] 2---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:19.120149+0800 GCD[4000:163392] 2---<NSThread: 0x60400006b600>{number = 1, name = main}
2018-07-18 14:38:19.120473+0800 GCD[4000:164570] SyncAndMain---end
6、异步执行 + 主队列
//6.异步执行 + 主队列
- (instancetype)initAsyncAndMainDispatch {
    if (self = [super init]) {
        NSLog(@"currentThread---%@",[NSThread currentThread]);//打印当前线程
        NSLog(@"AsyncAndMain---begin");
        
        dispatch_queue_t queue = dispatch_get_main_queue();   //获取主线程
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时线程
                NSLog(@"1---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时线程
                NSLog(@"2---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        dispatch_async(queue, ^{
            for (int i=0; i<2; i++) {
                [NSThread sleepForTimeInterval:2];            //模拟耗时线程
                NSLog(@"3---%@",[NSThread currentThread]);    //打印当前线程
            }
        });
        NSLog(@"AsyncAndMain---end");
    }
    return self;
}

输出结果:

2018-07-18 14:44:03.921354+0800 GCD[4125:168926] currentThread---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:03.921575+0800 GCD[4125:168926] AsyncAndMain---begin
2018-07-18 14:44:03.921763+0800 GCD[4125:168926] AsyncAndMain---end
2018-07-18 14:44:05.926029+0800 GCD[4125:168926] 1---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:07.928790+0800 GCD[4125:168926] 1---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:09.931443+0800 GCD[4125:168926] 2---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:11.933365+0800 GCD[4125:168926] 2---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:13.935818+0800 GCD[4125:168926] 3---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:44:15.937064+0800 GCD[4125:168926] 3---<NSThread: 0x60000006ce00>{number = 1, name = main}
7、同步执行 + 全局并发队列

由于全局并发队列等同于普通并发队列,所以该操作等同于同步执行 + 并发队列,请参考 1、同步执行 + 并发队列

8、异步执行 + 全局并发队列

由于全局并发队列等同于普通并发队列,所以该操作等同于异步执行 + 并发队列,请参考 2、异步执行 + 并发队列

9、GCD栅栏方法:dispatch_barrier_async
//9.GCD栅栏方法
- (void)dispatchBarrier {
    NSLog(@"currentThread --- %@",[NSThread currentThread]);
    NSLog(@"dispatchBarrier --- Begin");
    
    dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1---%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2---%@",[NSThread currentThread]);
        }
    });
    //栅栏方法
    dispatch_barrier_async(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3---%@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"4---%@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"5---%@",[NSThread currentThread]);
        }
    });
    NSLog(@"dispatchBarrier --- end");
}

输出结果:

2018-07-18 14:59:21.577599+0800 GCD[4125:168926] currentThread --- <NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 14:59:21.577839+0800 GCD[4125:168926] dispatchBarrier --- Begin
2018-07-18 14:59:21.578039+0800 GCD[4125:168926] dispatchBarrier --- end
2018-07-18 14:59:23.581183+0800 GCD[4125:169172] 2---<NSThread: 0x604000273ec0>{number = 4, name = (null)}
2018-07-18 14:59:23.581191+0800 GCD[4125:180793] 1---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:25.585534+0800 GCD[4125:169172] 2---<NSThread: 0x604000273ec0>{number = 4, name = (null)}
2018-07-18 14:59:25.585605+0800 GCD[4125:180793] 1---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:27.589468+0800 GCD[4125:180793] 3---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:29.594449+0800 GCD[4125:180793] 3---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:31.599255+0800 GCD[4125:180793] 4---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:31.599255+0800 GCD[4125:169172] 5---<NSThread: 0x604000273ec0>{number = 4, name = (null)}
2018-07-18 14:59:33.603883+0800 GCD[4125:180793] 4---<NSThread: 0x600000477880>{number = 3, name = (null)}
2018-07-18 14:59:33.603883+0800 GCD[4125:169172] 5---<NSThread: 0x604000273ec0>{number = 4, name = (null)}
10、GCD延时执行方法:dispatch_after
//10.GCD延时执行方法
- (void)dispatchAfter {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  //打印当前线程
    NSLog(@"dispatchAfter---begin");
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"after---%@",[NSThread currentThread]);      //打印当前线程
    });
    NSLog(@"dispatchAfter---end");
}

输出结果:

2018-07-18 15:08:27.072470+0800 GCD[4125:168926] currentThread---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:08:27.072737+0800 GCD[4125:168926] dispatchAfter---begin
2018-07-18 15:08:27.072927+0800 GCD[4125:168926] dispatchAfter---end
2018-07-18 15:08:29.073087+0800 GCD[4125:168926] after---<NSThread: 0x60000006ce00>{number = 1, name = main}
11、GCD单例:dispatch_once
#import "DispatchOnce.h"

static DispatchOnce * _onceManager;
@implementation DispatchOnce

//单例
+ (instancetype)dispatchOnceManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _onceManager = [[DispatchOnce alloc]init];
    });
    return _onceManager;
}

+ (instancetype)dispatchManager {
    _onceManager = [[DispatchOnce alloc]init];
    return _onceManager;
}

@end
//打印创建对象地址
DispatchOnce * one = [DispatchOnce dispatchOnceManager];
DispatchOnce * two = [DispatchOnce dispatchOnceManager];
DispatchOnce * three = [DispatchOnce dispatchManager];
DispatchOnce * four = [DispatchOnce dispatchManager];
NSLog(@"one  :%@",one);
NSLog(@"two  :%@",two);
NSLog(@"three:%@",three);
NSLog(@"four :%@",four);

输出结果:

2018-07-18 15:12:01.385630+0800 GCD[4125:168926] one  :<DispatchOnce: 0x60400001bfd0>
2018-07-18 15:12:01.385830+0800 GCD[4125:168926] two  :<DispatchOnce: 0x60400001bfd0>
2018-07-18 15:12:01.385957+0800 GCD[4125:168926] three:<DispatchOnce: 0x60400001b6a0>
2018-07-18 15:12:01.386151+0800 GCD[4125:168926] four :<DispatchOnce: 0x60400001aad0>
12、GCD快速迭代方法:dispatch_apply
//12.GCD 快速迭代方法:dispatch_apply
- (instancetype)initDispatchApplyManager {
    if (self = [super init]) {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        NSLog(@"apply---begin");
        dispatch_apply(5, queue, ^(size_t index) {
            NSLog(@"%ld --- %@",index,[NSThread currentThread]);
        });
        NSLog(@"apply---end");
    }
    return self;
}

输出结果:

2018-07-18 15:18:23.522423+0800 GCD[4125:168926] apply---begin
2018-07-18 15:18:23.524855+0800 GCD[4125:168926] 0 --- <NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:18:23.524875+0800 GCD[4125:194598] 1 --- <NSThread: 0x604000274b00>{number = 5, name = (null)}
2018-07-18 15:18:23.524926+0800 GCD[4125:180800] 2 --- <NSThread: 0x600000478000>{number = 6, name = (null)}
2018-07-18 15:18:23.524982+0800 GCD[4125:194608] 3 --- <NSThread: 0x604000271b80>{number = 7, name = (null)}
2018-07-18 15:18:23.525190+0800 GCD[4125:168926] 4 --- <NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:18:23.525362+0800 GCD[4125:168926] apply---end
13、GCD队列组:dispatch_group

如果我们在一个线程中异步执行几个耗时操作,但我们想等这几个耗时操作都完成之后再去执行其他操作,这时候我们就可以用到队列组dispatch_group了。

使用方式:调用队列组的 dispatch_group_async 先把任务放到队列中,然后将队列放入队列组中。或者使用队列组的dispatch_group_enterdispatch_group_leave 组合来实现dispatch_group_async。或者调用队列组的 dispatch_group_notify 回到指定线程执行任务。或者使用dispatch_group_wait 回到当前线程继续向下执行(会阻塞当前线程)

dispatch_group_notify
- (IBAction)dispatch_group_notify:(id)sender {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    dispatch_group_async(group, globalQueue, ^{
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        }
    });
    dispatch_group_async(group, globalQueue, ^{
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        }
    });
    dispatch_group_notify(group, mainQueue, ^{
        // 等前面的异步任务1、任务2都执行完毕后,回到主线程执行下边任务
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        }
        NSLog(@"group---end");
    });
}

输出结果:

2018-07-18 15:40:04.310925+0800 GCD[4125:168926] currentThread---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:40:04.311191+0800 GCD[4125:168926] group---begin
2018-07-18 15:40:06.316638+0800 GCD[4125:208985] 1---<NSThread: 0x6000004666c0>{number = 8, name = (null)}
2018-07-18 15:40:06.316645+0800 GCD[4125:180800] 2---<NSThread: 0x600000478000>{number = 6, name = (null)}
2018-07-18 15:40:08.319994+0800 GCD[4125:180800] 2---<NSThread: 0x600000478000>{number = 6, name = (null)}
2018-07-18 15:40:08.320003+0800 GCD[4125:208985] 1---<NSThread: 0x6000004666c0>{number = 8, name = (null)}
2018-07-18 15:40:10.321659+0800 GCD[4125:168926] 3---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:40:12.322667+0800 GCD[4125:168926] 3---<NSThread: 0x60000006ce00>{number = 1, name = main}
2018-07-18 15:40:12.323029+0800 GCD[4125:168926] group---end
dispatch_group_wait
- (IBAction)dispatch_group_wait:(id)sender {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group =  dispatch_group_create();
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_group_async(group, globalQueue, ^{
        // 追加任务1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        }
    });

    dispatch_group_async(group, globalQueue, ^{
        // 追加任务2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        }
    });
    //等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"group---end");
}

输出结果:

2018-07-18 15:46:21.438719+0800 GCD[5117:214014] currentThread---<NSThread: 0x600000260d80>{number = 1, name = main}
2018-07-18 15:46:21.439135+0800 GCD[5117:214014] group---begin
2018-07-18 15:46:23.440102+0800 GCD[5117:214604] 1---<NSThread: 0x60400046d440>{number = 4, name = (null)}
2018-07-18 15:46:23.440101+0800 GCD[5117:214057] 2---<NSThread: 0x600000666f00>{number = 3, name = (null)}
2018-07-18 15:46:25.446875+0800 GCD[5117:214057] 2---<NSThread: 0x600000666f00>{number = 3, name = (null)}
2018-07-18 15:46:25.447304+0800 GCD[5117:214604] 1---<NSThread: 0x60400046d440>{number = 4, name = (null)}
2018-07-18 15:46:25.453273+0800 GCD[5117:214014] group---end
dispatch_group_enter、dispatch_group_leave
- (IBAction)dispatch_groupClick:(id)sender {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 追加任务1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        }
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 追加任务2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        }
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步操作都执行完毕后,回到主线程.
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        }
        NSLog(@"group---end");
    });
    
    //    // 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
    //    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    //    NSLog(@"group---end");
}

输出结果:

2018-07-18 15:52:12.940112+0800 GCD[5242:219381] currentThread---<NSThread: 0x600000069200>{number = 1, name = main}
2018-07-18 15:52:12.940382+0800 GCD[5242:219381] group---begin
2018-07-18 15:52:14.946018+0800 GCD[5242:219651] 2---<NSThread: 0x600000469500>{number = 3, name = (null)}
2018-07-18 15:52:14.946018+0800 GCD[5242:219432] 1---<NSThread: 0x6000004762c0>{number = 4, name = (null)}
2018-07-18 15:52:16.951382+0800 GCD[5242:219432] 1---<NSThread: 0x6000004762c0>{number = 4, name = (null)}
2018-07-18 15:52:16.951397+0800 GCD[5242:219651] 2---<NSThread: 0x600000469500>{number = 3, name = (null)}
2018-07-18 15:52:18.953450+0800 GCD[5242:219381] 3---<NSThread: 0x600000069200>{number = 1, name = main}
2018-07-18 15:52:20.954745+0800 GCD[5242:219381] 3---<NSThread: 0x600000069200>{number = 1, name = main}
2018-07-18 15:52:20.954954+0800 GCD[5242:219381] group---end
14、GCD信号量:dispatch_semaphore
Dispatch Semaphore 提供了三个函数:
- (IBAction)useClick:(id)sender {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"semaphore---begin");
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    __block NSInteger num = 0;
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        num = 1;
        dispatch_semaphore_signal(semaphore);
    });
    
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"semaphore---end,num = %ld",num);
}

输出结果:

2018-07-18 16:05:37.412573+0800 GCD[5472:229493] currentThread---<NSThread: 0x60400007cdc0>{number = 1, name = main}
2018-07-18 16:05:37.412940+0800 GCD[5472:229493] semaphore---begin
2018-07-18 16:05:39.417126+0800 GCD[5472:229532] 1---<NSThread: 0x60000007e080>{number = 3, name = (null)}
2018-07-18 16:05:39.417295+0800 GCD[5472:229493] semaphore---end,num = 1
15、取消GCD任务两种方法:

Demo地址:GCD

「欢迎指正交流」0_0

上一篇下一篇

猜你喜欢

热点阅读