GCD的相关使用

一、同步执行 + 主队列

/**
 * 同步执行 + 主队列
 * 特点(主线程调用):互等卡主不执行。
 * 特点(其他线程调用):不会开启新线程,执行完一个任务,再执行下一个任务。
 */
- (void)syncMain {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"开启");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"结束");
}

运行结果:

currentThread---{number = 1, name = main}
开启

线程死锁。为什么呢?
- (void)syncMain {} ----> 任务AGCD同步任务 ----> 任务B
      任务A在主队列,并且已经开始执行(打印出currentThread),这个时候任务B被加入到主队列中,并且同步执行,且不能开新的线程。
      任务B得等Block函数执行完成,才能返回,然而主队列是串行的,得等任务A执行完才能去执行任务B的Block。
      造成了任务A在等任务B完成才能继续执行,但是串行队列中,又不能让任务B在任务A未完成之前开始执行,相互等待,造成了死锁。

二、同步执行 + 并发队列

/**
 * 同步执行 + 并发队列
 * 特点:在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。
 */
- (void)syncConcurrent {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"开启");
    
    dispatch_queue_t queue = dispatch_queue_create("syncConcurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"结束");
}

运行结果:

currentThread---{number = 1, name = main}
开启
1---{number = 1, name = main}
2---{number = 1, name = main}
结束

三、异步执行 + 并发队列

/**
 * 异步执行 + 并发队列
 * 特点:可以开启多个线程,任务交替(同时)执行。
 */
- (void)asyncConcurrent {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"开启");
    
    dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"结束");
}

运行结果:

currentThread---{number = 1, name = main}
开启
结束
1---{number = 5, name = (null)}
2---{number = 6, name = (null)}

四、同步执行 + 串行队列

/**
 * 同步执行 + 串行队列
 * 特点:不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。
 */
- (void)syncSerial {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"开启");
    
    dispatch_queue_t queue = dispatch_queue_create("syncSerial", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"结束");
}

运行结果:

currentThread---{number = 1, name = main}
开启
1---{number = 1, name = main}
2---{number = 1, name = main}
结束

五、异步执行 + 串行队列

/**
 * 异步执行 + 串行队列
 * 特点:会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务。
 */
- (void)asyncSerial {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"开启");
    
    dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"结束");
}

运行结果:

currentThread---{number = 1, name = main}
开启
结束
1---{number = 4, name = (null)}
2---{number = 4, name = (null)}

六、其他函数用法

1、dispatch_after

- (void)GCDDelay {
    NSLog(@"current_%@",[NSThread currentThread]);
    //主队列延时
    dispatch_time_t when_main = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_main, dispatch_get_main_queue(), ^{
        NSLog(@"main_%@",[NSThread currentThread]);
    });
    
    //全局队列延时
    dispatch_time_t when_global = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_global, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"global_%@",[NSThread currentThread]);
    });
    
    //自定义队列延时
    dispatch_queue_t customeQue = dispatch_queue_create("customeQue", DISPATCH_QUEUE_SERIAL);
    dispatch_time_t when_global_custom = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_global_custom, customeQue, ^{
        NSLog(@"when_global_custom_%@",[NSThread currentThread]);
    });
}
current_{number = 1, name = main}
main_{number = 1, name = main}
when_global_custom_{number = 7, name = (null)}
global_{number = 5, name = (null)}

      我们可以看到,当队列是主队列时,任务是在主线程执行;当队列为全局或自定义时,任务是在子线程中执行

2、dispatch_once

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    NSLog(@"current_%@",[NSThread currentThread]);
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
}
current_{number = 1, name = main}
{number = 1, name = main}

      程序运行期间,只会执行一次打印,任务在主线程中执行

3、dispatch_group_async & dispatch_group_notify

- (void)GCDGroup {
    
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"3---%@",[NSThread currentThread]);
    });
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
end_{number = 1, name = main}
1---{number = 6, name = (null)}
2---{number = 3, name = (null)}
3---{number = 3, name = (null)}

dispatch_group_asyncdispatch_get_global_queue时会开辟新的线程执行任务,任务会在子线程中执行
dispatch_group_notify只会在dispatch_group_async都执行完后才会执行

4、dispatch_barrier_async

- (void)GCDBarrier {
    
    NSLog(@"start_%@",[NSThread currentThread]);
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(myQueue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    //同步sync
    dispatch_barrier_sync(myQueue, ^{
        NSLog(@"barrier---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"3---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"4---%@",[NSThread currentThread]);
    });
    
    NSLog(@"end_%@",[NSThread currentThread]);
}
myQueue为自定义时:
start_{number = 1, name = main}
2---{number = 6, name = (null)}
1---{number = 5, name = (null)}
barrier---{number = 1, name = main}
end_{number = 1, name = main}
3---{number = 5, name = (null)}
4---{number = 6, name = (null)}

myQueue为:dispatch_get_global_queue(0,0)时
start_{number = 1, name = main}
barrier---{number = 1, name = main}
1---{number = 6, name = (null)}
2---{number = 7, name = (null)}
3---{number = 6, name = (null)}
end_{number = 1, name = main}
4---{number = 4, name = (null)}
  • 当队列为自定义时,使用dispatch_barrier_sync ()后,任务3、4必须等任务1、2执行完后才能执行
  • 当队列是dispatch_get_global_queue(0,0)时,就算使用了dispatch_barrier_sync (),执行顺序随机不固定
  • 当队列是dispatch_get_main_queue()时,死锁

5、dispatch_apply

- (void)GCDApply {
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    //重复执行
    dispatch_apply(5, myQueue, ^(size_t i) {
        NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
    });
}
myQueue为串行:
start_{number = 1, name = main}
第0次_{number = 1, name = main}
第1次_{number = 1, name = main}
第2次_{number = 1, name = main}
第3次_{number = 1, name = main}
第4次_{number = 1, name = main}
end_{number = 1, name = main}

myQueue为并行:
start_{number = 1, name = main}
第3次_{number = 6, name = (null)}
第2次_{number = 4, name = (null)}
第0次_{number = 1, name = main}
第1次_{number = 7, name = (null)}
第4次_{number = 5, name = (null)}
end_{number = 1, name = main}
  • 用于重复执行某个任务
  • 任务队列是串行队列时,重复执行的任务会按顺序执行
  • 任务队列是并行队列时,重复执行的任务会并发执行

6、dispatch_semaphore_create & dispatch_semaphore_wait & dispatch_semaphore_signal

- (void)GCDSemaphor {
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    //创建信号量,初始值不能小于0
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    //重复执行
    dispatch_apply(5, myQueue, ^(size_t i) {
        //等待降低信号量,也就是信号量-1
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
        //提高信号量,也就是信号量+1
        dispatch_semaphore_signal(semaphore);
    });
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
第0次_{number = 1, name = main}
第1次_{number = 1, name = main}
第2次_{number = 1, name = main}
第3次_{number = 1, name = main}
第4次_{number = 1, name = main}
end_{number = 1, name = main}

异步任务使用

- (void)GCDSemaphorAsync {
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    //创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第一次任务开始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第一次任务结束_%@",[NSThread currentThread]);
        //会将信号量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第二次任务开始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第二次任务结束_%@",[NSThread currentThread]);
        //会将信号量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第三次任务开始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第三次任务结束_%@",[NSThread currentThread]);
        //会将信号量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
第一次任务开始_{number = 6, name = (null)}
第一次任务结束_{number = 6, name = (null)}
第二次任务开始_{number = 6, name = (null)}
第二次任务结束_{number = 6, name = (null)}
第三次任务开始_{number = 6, name = (null)}
第三次任务结束_{number = 6, name = (null)}
end_{number = 1, name = main}
  • dispatch_semaphore_create创建信号量,初始值不能小于0
  • dispatch_semaphore_wait等待降低信号量,也就是信号量-1
  • dispatch_semaphore_signal提高信号量,也就是信号量+1
  • dispatch_semaphore_waitdispatch_semaphore_signal通常配对使用
主要作用:
  • 保持线程同步,将异步执行任务转换为同步执行任务
  • 保证线程 安全,为线程加锁

你可能感兴趣的:(GCD的相关使用)