【iOS开发】GCD中央调度器

GCD (grand center dispatch)

任务:需要执行的操作
队列:线性队列 并发队列 同步队列

几种组合方式
同步+并发

执行特点:

同步队列+同步
异步+并发
异步+同步

队列:

常用三种方式创建
dispatch_get_main_queue
dispatc_queue_create
dispatch_global_queue

三种队列:
串行队列
并发队列
主队列

任务:

两种执行方式

    dispatch_async(queue, ^{
        //异步执行代码
    });
    dispatch_sync(queue, ^{
        //同步执行代码
    });

任务和队列的组合方式

不同执行结果

  1. 串行队列+同步执行
- (void)syncTaskWithSerial {
    
    NSLog(@"currentThread:%@",[NSThread currentThread]);
    NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t serialQueue = dispatch_queue_create("com.cao.thread.demo", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(serialQueue, ^{
        NSLog(@"currentThread-1:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"currentThread-2:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"currentThread-3:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    
    //output
//    ThreadTest[505:64898] currentThread:{number = 1, name = main}
//    ThreadTest[505:64898] isMainThread:YES
//    ThreadTest[505:64898] currentThread-1:{number = 1, name = main}
//    ThreadTest[505:64898] isMainThread:YES
//    ThreadTest[505:64898] currentThread-2:{number = 1, name = main}
//    ThreadTest[505:64898] isMainThread:YES
//    ThreadTest[505:64898] currentThread-3:{number = 1, name = main}
//    ThreadTest[505:64898] isMainThread:YES
    
}
  1. 没有开启新线程

  2. 任务顺序执行

  3. 串行队列+异步执行

//串行队列 + 异步执行
- (void)asyncTaskWithSerial {
    
    NSLog(@"currentThread:%@",[NSThread currentThread]);
    NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t serialQueue = dispatch_queue_create("com.cao.thread.demo", DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue, ^{
        NSLog(@"currentThread-1:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"currentThread-2:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"currentThread-3:%@",[NSThread currentThread]);
        NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    
    //output
//   ThreadTest[509:65509] currentThread:{number = 1, name = main}
//   ThreadTest[509:65509] isMainThread:YES
//   ThreadTest[509:65546] currentThread-1:{number = 3, name = (null)}
//   ThreadTest[509:65546] isMainThread:NO
//   ThreadTest[509:65546] currentThread-2:{number = 3, name = (null)}
//   ThreadTest[509:65546] isMainThread:NO
//   ThreadTest[509:65546] currentThread-3:{number = 3, name = (null)}
//   ThreadTest[509:65546] isMainThread:NO

}
  1. 开启了新线程

  2. 顺序执行了(虽然是异步任务,但是因为是同步队列,执行顺序依然是同步)

  3. 并发队列+ 同步

- (void)syncTaskWithConcurrent{
    NSLog(@"currentThread:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t concurrentQueue = dispatch_queue_create("coms.cao.thread.demo", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_sync(concurrentQueue, ^{
        NSLog(@"currentThread-1:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_sync(concurrentQueue, ^{
        NSLog(@"currentThread-2:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_sync(concurrentQueue, ^{
        NSLog(@"currentThread-3:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    // 预计:1. 开新线程 一个 (错误) 2. 顺序执行
    
    //Output
//    ThreadTest[518:66775] currentThread:{number = 1, name = main} isMainThread:YES
//    ThreadTest[518:66775] currentThread-1:{number = 1, name = main} isMainThread:YES
//    ThreadTest[518:66775] currentThread-2:{number = 1, name = main} isMainThread:YES
//    ThreadTest[518:66775] currentThread-3:{number = 1, name = main} isMainThread:YES
    
}
  1. 未开启新线程

  2. 顺序执行

  3. 并发队列+ 异步

- (void)asyncTaskWithConcuarrent{
    NSLog(@"currentThread:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t concurrentQueue = dispatch_queue_create("coms.cao.thread.demo", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"currentThread-1:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"currentThread-2:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"currentThread-3:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    // 预计:1. 开新线程 2. 异步执行
    //Output
//   ThreadTest[521:67287] currentThread:{number = 1, name = main} isMainThread:YES
//   ThreadTest[521:67326] currentThread-2:{number = 3, name = (null)} isMainThread:NO
//   ThreadTest[521:67326] currentThread-3:{number = 3, name = (null)} isMainThread:NO
//   ThreadTest[521:67327] currentThread-1:{number = 4, name = (null)} isMainThread:NO
    
}
  1. 开新线程

  2. 异步执行

  3. 主队列+ 同步
    Thread 1: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)

- (void)syncTaskWithMain{
    NSLog(@"currentThread:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    dispatch_sync(mainQueue, ^{
        NSLog(@"currentThread-1:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_sync(mainQueue, ^{
        NSLog(@"currentThread-2:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_sync(mainQueue, ^{
        NSLog(@"currentThread-3:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
}

// 死锁:
因为是同步执行,任务等待函数调用处执行完毕,然后执行。 函数调用处执行完毕需要同步任务执行完,两者相互等待发生死锁

  1. 主队列+ 异步
- (void)asyncTaskWithMain{
    NSLog(@"currentThread:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    dispatch_async(mainQueue, ^{
        NSLog(@"currentThread-1:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"currentThread-2:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    dispatch_async(mainQueue, ^{
        NSLog(@"currentThread-3:%@ isMainThread:%@",[NSThread currentThread],[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
    });
    
    //output
//   ThreadTest[531:68798] currentThread:{number = 1, name = main} isMainThread:YES
//   ThreadTest[531:68798] currentThread-1:{number = 1, name = main} isMainThread:YES
//   ThreadTest[531:68798] currentThread-2:{number = 1, name = main} isMainThread:YES
//   ThreadTest[531:68798] currentThread-3:{number = 1, name = main} isMainThread:YES
}
  1. 没有开启新线程
  2. 同步执行

嵌套执行

串行异步+串行同步

 (void)testEmbedExcute {
    NSLog(@"currentThread:%@",[NSThread currentThread]);
       NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
       dispatch_queue_t serialQueue = dispatch_queue_create("com.cao.thread.demo", DISPATCH_QUEUE_SERIAL);
       dispatch_async(serialQueue, ^{
           NSLog(@"currentThread-1:%@",[NSThread currentThread]);
           NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
           
           dispatch_sync(serialQueue, ^{
               NSLog(@"currentThread-2:%@",[NSThread currentThread]);
               NSLog(@"isMainThread:%@",[[NSThread currentThread] isMainThread] ? @"YES":@"NO");
           });
           
       });
    
}

Thread 2: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)
发生死锁:

【iOS开发】GCD中央调度器_第1张图片

GCD 函数方法

  1. 栅栏函数
- (void)barrierTask {
    dispatch_queue_t queue = dispatch_queue_create("com.cao.thread.demo", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"start");
    
    dispatch_async(queue, ^{
       NSLog(@"currentThread-1:%@",[NSThread currentThread]);
    });
    dispatch_barrier_sync(queue, ^{
        NSLog(@"currentThread-2:%@",[NSThread currentThread]);
    });
    dispatch_barrier_sync(queue, ^{
        NSLog(@"currentThread-3:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
       NSLog(@"currentThread-4:%@",[NSThread currentThread]);
    });
    
//    ThreadTest[555:73805] start
//    ThreadTest[555:73850] currentThread-1:{number = 3, name = (null)}
//    ThreadTest[555:73805] currentThread-2:{number = 1, name = main}
//    ThreadTest[555:73805] currentThread-3:{number = 1, name = main}
//    ThreadTest[555:73850] currentThread-4:{number = 3, name = (null)}
    
}

1.阻塞线程同步执行

2.延迟执行

   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5), dispatch_get_main_queue(), ^{
        NSLog(@"after-1:%@",[NSThread currentThread]);
    });

3.调度组

Groups allow you to aggregate a set of tasks and synchronize behaviors on the group. You attach multiple blocks to a group and schedule them for asynchronous execution on the same queue or different queues. When all blocks finish executing, the group executes its completion handler. You can also wait synchronously for all blocks in the group to finish executing.
调度组简单就是把异步任务进行分组,等待所有的任分组都执行完毕后再回到指定的线程执行任务。

接口:
创建:
dispatch_group_create
将任务添加到队列中
dispatch_group_async 将任务添加到队列中,然后将队列添加到调度组中
dispatch_group_notify 回到指定线程执行任务

两个成对出现
dispatch_group_leave 将实现队列添加到调度组
dispatch_group_wait 阻塞当前线程

- (void)groupNotifyTest{
    NSLog(@"current thread:%@",[NSThread currentThread]);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"current thread-1:%@",[NSThread currentThread]);
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];
         NSLog(@"current thread-2:%@",[NSThread currentThread]);
    });
    
    
    //异步任务执行完毕后 执行添加的通知
    dispatch_notify(group, dispatch_get_main_queue(), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"current thread-3:%@",[NSThread currentThread]);
        NSLog(@"group-end");
    });
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"dispatch_group_wait后继续执行任务");
    
//   ThreadTest[598:81370] current thread:{number = 1, name = main}
//   ThreadTest[598:81406] current thread-1:{number = 3, name = (null)}
//   ThreadTest[598:81407] current thread-2:{number = 4, name = (null)}
//   ThreadTest[598:81370] dispatch_group_wait后继续执行任务
//   ThreadTest[598:81370] current thread-3:{number = 1, name = main}
//   ThreadTest[598:81370] group-end
    
}
  1. dispatch_group_wait阻塞线程等待执行
  2. dispatch_notify 添加到group组的任务执行完后执行block

dispatch_group_enter和dispatch_group_leave对实现将队列添加到调度组的情况,dispatch_group_enter 标志着在group的任务数+1,dispatch_group_leave标志在group中的任务数-1,表示已经完成了一个任务。

- (void)groupEnterTest {
    NSLog(@"current thread:%@",[NSThread currentThread]);
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"current thread-1:%@",[NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"current thread-2:%@",[NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    //异步任务执行完毕后 执行添加的通知
    dispatch_notify(group, dispatch_get_main_queue(), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"current thread-3:%@",[NSThread currentThread]);
        NSLog(@"group-end");
    });
}

成对出现

  1. 信号量
    GCD中的信号量是指Dispatch Semaphore,是持有计数的信号,当信号量<0时就会一直等待即阻塞所在线程,否则就可以正常执行。信号量可以保持线程同步,降一补执行任务转换成同步任务执行,同时保持线程的安全。
- (void)semaphoreTest {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    __block int a =0;
    while (a<5) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"a里面的值:%d",a);
            dispatch_semaphore_signal(semaphore);
            a++;
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
    NSLog(@"外面的a的值:%d",a);
}
  1. 调度源- Dispatch_source
    An object that coordinates the processing of specific low-level system events, such as file-system events, timers, and UNIX signals.
    调度源是协调特殊低级别系统时间处理的基本数据类型,GCD支持诸如定时器调度源,信号调度源,描述符调度源,进程调度源,端口调度源,自定义调度源。

你可能感兴趣的:(IOS,开发)