1.向并行队列提交同步任务,(根据显示结果可知:全部任务所有在主线程执行,全部任务都是按顺序执行的)html
//线程与线程之间的执行速度多是不肯定的 //1. 建立一个并行队列 dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT); //并行队列中提交多个异步任务,任务的顺序不能肯定 //同步提交任务任务的顺序能够肯定 dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务一:%d", i); } }); NSLog(@"---1---"); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务二:%d", i); } }); NSLog(@"---2---"); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务三:%d", i); } }); NSLog(@"---3---");
2.向并行队列提交异步任务(根据结果:全部任务都是在非主线程中执行的,并且任务执行的顺序是不肯定的)编程
//并行队列中提交多个异步任务,任务的顺序不能肯定 dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务一:%d", i); } }); NSLog(@"---1---"); dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务二:%d", i); } }); NSLog(@"---2---"); dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务三:%d", i); } }); NSLog(@"---3---");
1.向串行队列同步提交任务(从结果可知:全部任务都在主线程中执行,全部任务都是按顺序执行的)数据结构
//1. 建立串行队列,一个串行队列对应一个线程 //1.1. 第一个参数是队列的名称 //1.2. 第二个参数是队列的类型,NULL表示串行队列 dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL); //2. 若是任务在不一样的线程中执行,那么它们的执行顺序是不肯定的 dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务一:%d", i); } }); NSLog(@"---1---"); dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务二:%d", i); } }); NSLog(@"---2---"); dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务三:%d", i); } }); NSLog(@"---3---");
2.向串行队列提交异步任务(从结果可知:全部的任务都是在非主线程中执行的,全部的任务都是按顺序执行的)并发
dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务一:%d", i); } }); NSLog(@"---1---"); dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务二:%d", i); } }); NSLog(@"---2---"); dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } for (int i = 0; i < 100; i++) { NSLog(@"任务三:%d", i); } }); NSLog(@"---3---");
结果对比:异步
1.不论是串行队列仍是并行队列,同步提交任务都是在主线程中执行的,异步提交任务都是在非主线程中执行的(这里相对于3.4来说的)async
2.并行队列的任务,若是不在同一线程,能够与主线程同时执行,主线程中的任务优先其余线程的任务执行,但不排除其余线程的任务和主线程的任务同时间进行函数
3.同步提交任务,任务所在的线程与提交任务所在的线程是同样的优化
4.异步提交任务,任务所在的线程与提交任务所在的线程是不同的spa
5.同一线程,全部任务都是先进先出按顺序来的(串行同步,并行同步都在主线程)线程
6.串行异步,任务在同一个线程,任务所在的线程与提交任务所在的线程是不同的(因此出现任务一和主线程的任务先执行,任务二和任务三后执行,由于任务一二三在同一个线程)
7.并行异步,任务在不一样线程,任务所在的线程与提交任务所在的线程是不同的(因此出现任务和主线程的任务都是同时执行)
因此根据上面的总结能够体会到,任务的执行顺序和会不会阻塞,我门只须要判断清楚任务所在的线程就能够了,不一样线程能够同时执行,同一线程只能按顺序执行
最后只需记住多个任务同时执行用: 并行异步 两个任务同时执行用:串行异步 全部任务按前后顺序执行 :串行同步,并行同步 可是这里只是相对于一个线程编程的时候,好比主线程,若是在主线程里面建立一个其余的线程,而后同步提交任务,咱们是否是也能够实现两个甚至是多个任务同时运行了,这个还有待验证
概念这里参考 http://www.mamicode.com/info-detail-1010323.html 为了避免麻烦就直接复制粘贴了
首先明确一下“同步&异步”“串行&并发”这两组基本概念:
同步执行:好比这里的dispatch_sync,这个函数会把一个block加入到指定的队列中,并且会一直等到执行完blcok,这个函数才返回。所以在block执行完以前,调用dispatch_sync方法的线程是阻塞的。
与之对应的就有“异步执行”的概念:
异步执行:通常使用dispatch_async,这个函数也会把一个block加入到指定的队列中,可是和同步执行不一样的是,这个函数把block加入队列后不等block的执行就马上返回了。
接下来看一看另外一组相对的概念:“串行&并发”
串行队列:好比这里的dispatch_get_main_queue。这个队列中全部任务,必定按照先来后到的顺序执行。不只如此,还能够保 证在执行某个任务时,在它前面进入队列的全部任务确定执行完了。对于每个不一样的串行队列,系统会为这个队列创建惟一的线程来执行代码。
与之相对的是并发队列:
并发队列:好比使用dispatch_get_global_queue。这个队列中的任务也是按照先来后到的顺序开始执行,注意是开始,可是它们的执行结束时间是不肯定的,取决于每一个任务的耗时。对于n个并发队列,GCD不会建立对应的n个线程而是进行适当的优化
总结一下,到底什么是死锁。首先,虽然刚刚咱们提到了队列和线程,以及它们之间的对应关系,可是死锁必定是针对线程 而言的,队列只是GCD给出的抽象数据结构。所谓的死锁,必定是发生在一个或多个线程之间的。那么死锁和线程阻塞的关系呢,能够这么理解,双向的阻塞致使 了死锁。由于阻塞是线程中常常发生的事情,最多就是主线程的阻塞影响了用户体验。而一旦出现了双向的阻塞,就致使了死锁。咱们能够看到,主线程是串行的, 在执行某一个任务的时候线程被阻塞了,而这个任务(dispatch_sync)在执行时,又要求阻塞主线程,从而致使了互相的阻塞,也就是死锁
分析:若是阻塞时间过长久会造成“界面假死”,若是双向阻塞就会造成死锁,这两种状况的造成咱们就不考虑异步提交了,由于异步提交是根本不会造成阻塞,因此咱们只看同步提交的状况
//1. 主队列里的任务必定在主线程上执行 //2. 不该该在主线程中执行耗时的任务,不然会致使主线程阻塞,从而使界面“假死” dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL); dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主线程"); }else{ NSLog(@"非主线程"); } //获取当前时间,秒钟 CFAbsoluteTime begin = CFAbsoluteTimeGetCurrent(); //整个管理文件或者文件夹 [[NSFileManager defaultManager] copyItemAtPath:@"/Users/zhouzhi/百度云同步盘/电子专业书籍" toPath:@"/Users/zhouzhi/Desktop/电子书" error:nil]; //获取结束时间点 CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); //打印消耗的时间 NSLog(@"%.2f秒", end - begin); }); NSLog(@"任务执行完成了");
除了同步提交任务到mainQueue会造成死锁,其余都是界面假死:说明只有同步向当前对列提交任务才会形成死锁