Grand Central Dispatch(GCD)是 Apple 开发的一个多核编程的解决方法。它是一套纯 C 语言的 API
,主要用于优化应用程序以支持多核处理器以及其余对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。编程
任务即执行操做
,就是线程中须要执行的代码。在GCD
中就是放在block
中执行的代码都是任务。任务分为同步任务(sync)
和异步任务(async)
。markdown
同步任务(sync)
:同步添加到队列当中,当前面的任务没有执行完毕时会一直等待,直到前面的任务执行完毕才会执行当前加入的任务。不能够在新的线程中执行,不具有开辟新的线程能力。异步任务(async)
:异步添加到队列当中,无需等待前面的任务执行完成才执行,加入队列就会执行。能够在新的线程中执行,具有开辟新的线程能力。注意:具有开启新线程的能力不表明必定开启新的线程
指执行任务的队列,就是等待执行的任务列表,遵循先进先出IFFO
原则。在GCD中有串行队列(Serial Dispatch Queue)
和并行队列(Concurrent Dispatch Queue),又叫并发队列
。并发
串行队列(Serial Dispatch Queue)
:只开启一个线程
,每次只有一个任务执行,任务执行完成后才会执行下一个任务。并行队列(Concurrent Dispatch Queue)
:可让多个任务同时执行,能够开启多个线程来执行多个任务。注意:并发队列只有在异步函数下才有效
。//第一个参数是队列的名字,自定义;第二个参数表示是串行仍是并发
//DISPATCH_QUEUE_SERIAL = NULL,所以DISPATCH_QUEUE_SERIAL能够用NULL代替建立串行队列
dispatch_queue_t queue = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
复制代码
//第一个参数是队列的名字,自定义;第二个参数表示是串行仍是并发
dispatch_queue_t queue = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);
复制代码
//建立同步任务(queue是队列)
dispatch_sync(queue, ^{
});
复制代码
//建立异步任务(queue是队列)
dispatch_async(queue, ^{
});
复制代码
综上所述,咱们能够得出一共四种组合外加两种特殊的队列,即异步
-(void)serialSysncText {
//串行队列
dispatch_queue_t serial = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
NSLog(@"串行同步任务开始");
dispatch_sync(serial, ^{
sleep(1);
for (int i = 0; i<3; i++) {
NSLog(@"串行同步任务1 = %d",i);
}
});
dispatch_sync(serial, ^{
sleep(1);
for (int i = 0; i<3; i++) {
NSLog(@"串行同步任务2 = %d",i);
}
});
NSLog(@"串行同步任务结束");
}
复制代码
从运行结果当中,咱们能够看到串行队列中的同步任务都是按照前后顺序依次执行的。async
-(void)concurrentAsysncText {
//并发队列
dispatch_queue_t concurrent = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"并发同步任务开始");
dispatch_sync(concurrent, ^{
sleep(1);
for (int i = 0; i<3; i++) {
NSLog(@"并发同步任务1 = %d",i);
}
});
dispatch_sync(concurrent, ^{
sleep(1);
for (int i = 0; i<3; i++) {
NSLog(@"并发同步任务2 = %d",i);
}
});
NSLog(@"并发同步任务结束");
}
复制代码
从结果得知,并发队列执行的同步任务也是
按照顺序依次执行
的,由于它们都在主线程中执行
的,没有开启新的线程。感兴趣的小伙伴能够打印下线程看下。函数
-(void)serialAsysncText {
//串行队列
dispatch_queue_t serial = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
NSLog(@"串行异步任务开始");
dispatch_async(serial, ^{
for (int i = 0; i<3; i++) {
sleep(1);
NSLog(@"串行异步任务1 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
dispatch_async(serial, ^{
for (int i = 0; i<3; i++) {
sleep(1);
NSLog(@"串行异步任务2 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
NSLog(@"串行异步任务结束");
}
复制代码
从运行结果能够看出,优化
-(void)concurrentAsysncText {
//并发队列
dispatch_queue_t concurrent = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"并发异步任务开始");
dispatch_async(concurrent, ^{
for (int i = 0; i<3; i++) {
sleep(1);
NSLog(@"并发异步任务1 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
dispatch_async(concurrent, ^{
for (int i = 0; i<3; i++) {
sleep(1);
NSLog(@"并发异步任务2 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
NSLog(@"并发异步任务结束");
}
复制代码
从运行结果来看,spa
因为主队列是串行队列,它不能在主线程中调用主队列同步任务,以下所示崩溃缘由就是同步任务放在了主线程中,须要等待主线程执行完毕才能够,而主线程须要等待该方法执行完成,
二者互相等待形成死锁
,因此崩溃了。线程
代码3d
//使用 NSThread 的 detachNewThreadWithBlock 方法会建立线程
[NSThread detachNewThreadWithBlock:^{
[self mainSysncText];
}];
-(void)mainSysncText {
NSLog(@"当前所在的线程:%@",[NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
for (int i = 0; i<2; i++) {
sleep(1);
NSLog(@"主队列同步任务1 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
dispatch_sync(dispatch_get_main_queue(), ^{
for (int i = 0; i<2; i++) {
sleep(1);
NSLog(@"主队列同步任务2 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
}
复制代码
执行结果
因为主队列是串行队列,因此主队列+异步任务
就至关于串行队列+异步任务
-(void)mainAsysncText {
NSLog(@"当前所在的线程:%@",[NSThread currentThread]);
NSLog(@"主队列异步任务开始");
dispatch_async(dispatch_get_main_queue(), ^{
for (int i = 0; i<2; i++) {
sleep(1);
NSLog(@"主队列异步任务1 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
dispatch_async(dispatch_get_main_queue(), ^{
for (int i = 0; i<2; i++) {
sleep(1);
NSLog(@"主队列异步任务2 = %d",i);
NSLog(@"当前线程:%@",[NSThread currentThread]);
}
});
NSLog(@"主队列异步任务结束");
}
复制代码
效果等同于
串行队列+异步任务