同步、异步与串行、并行的关系
前言:
做这块知识展示目的是为了帮助自己对多线程中的知识点做一个回顾,所以可能讲解上面会很简单,但是重点是要将知识点弄清晰,如果你对多线程不是很了解,那么可以看看,当然本文中如果存在错误,也欢迎大家指正。
多线程中的队列:
串行队列、 并行队列、全局队列、主队列
执行的方法:
同步执行和异步执行
线程分类:
单线程和多线程,咱们平时用的最多的就是GCD和NSOperation,他们之间的核心区别在于GCD是将一个任务添加到队列中,然后指定任务执行的方法,而NSOperation则是将一个操作添加到队列中。
废话说完了,咱们现在就来看一下,将上面的各种组合做一个排列看看结果会是怎么样的?
1.串行队列,同步执行

运行结果

执行结果可以清楚的看到全在主线程执行,并且是按照顺序执行,循环结束之后主线程的打印才输出。
2.串行队列,异步执行

运行结果

结果显示,系统开了1条异步线程,因此全部在线程3执行,并且是顺序执行。主线程打印虽然在最上面,但是这个先后顺序是不确定,如果睡个0.001秒,主线程的打印会混在中间。
3.并发队列,异步执行

运行结果

结果显示,主线程的打印还是混在中间不确定的,因为异步线程就是谁也不等谁,可以同时执行。系统开了多条线程,并且执行的顺序也是乱序的
4.并发队列,同步执行

运行结果

这个运行结果和第1种的串行队列,同步执行是一模一样的。 因为同步任务的概念就是不允许单开线程,在这里虽然他是并发的,可以允许程序同时运行,但是系统只有一条线程,所以他只能按照顺序执行,所以一旦是同步执行的,前面是什么队列都不重要了。
5.主队列,异步执行

运行结果

结果显示有点出人意料。主线程在睡会之后才打印,循环一直在等着。因为主队列的任务虽然会加到主线程中执行,但是如果主线程里也有任务就必须等主线程任务执行完才轮到主队列的。
6.主队列,同步执行

运行结果
运行结果为程序崩溃
崩溃的原因是循环等待,主队列的东西要等主线程执行完,而因为是同步执行不能开线程,所以下面的任务要等上面的任务执行完,所以卡死。这是排列组合中唯一一个会卡死的组合。
7.同步任务的使用场景

运行结果

结果显示,“用户登陆”在主线程打印,后两个在异步线程打印。上面的“用户登陆”使用同步执行,后面的扣费和下载都是异步执行。所以“用户登陆”必须第一个打印出来不管等多久,然后后面的两个异步和主线程打印会不确定顺序的打印。这就是日常开发中,那些后面对其有依赖的必须要先执行的任务使用同步执行,然后反正都要执行先后顺序无所谓的使用异步执行。
8.block异步任务包裹同步任务

运行结果

因为整个block是在异步执行的,所以即使里面“用户登陆”是同步执行,那也无法在主线程中执行,只能开一条异步线程执行,后面我故意将一和二任务换了一下位置。在异步执行里面,因为项目是并发的,可以同时执行,而且查看动作在用户登录前面,所以它是可以比用户登录先执行也可能比用户登录后执行,但是因为用户登录是同步执行的,所以下载任务必须要等用户登录任务先执行完他才会执行,而主线程跟整个队列里面的任务之间,因为task是异步的,所以他们之间的先后顺序也是随机的,随意主线程执行的顺序可能在任何一个位置。
9.全局队列,异步执行

运行结果

全局队列,实际上就相当于并发队列,所以并发队列异步执行,他会开启多条子线程去执行任务,并且他跟主线程之间的执行顺序也是随机的。
10.全局队列,同步执行

运行结果

全局队列,同步执行,因为同步执行它不能开启新线程,所以所有的程序只能在主线程中按照顺序依次执行。全局队列的本质就是并发队列,只是在后面加入了,“服务质量”,和“调度优先级” 两个参数,这两个参数一般为了系统间的适配,最好直接填0和0。
总结:
-
开不开线程,取决于执行任务的函数,同步不开,并且同步会阻塞线程等到同步任务执行完以后才会执行其他任务,异步开,异步不会阻塞线程。
-
开几条线程,取决于队列,串行开一条,并发开多条(异步)
-
主队列: 专门用来在主线程上调度任务的"队列",主队列不能在其他线程中调度任务!
-
如果主线程上当前正在有执行的任务,主队列暂时不会调度任务的执行!主队列同步任务,会造成死锁。原因是循环等待
-
同步任务可以队列调度多个异步任务前,指定一个同步任务,让所有的异步任务,等待同步任务执行完成,这是依赖关系。
-
全局队列:并发,能够调度多个线程,执行效率高,但是相对费电。 串行队列效率较低,省电省流量,或者是任务之间需要依赖也可以使用串行队列。
-
也可以通过判断当前用户的网络环境来决定开的线程数。WIFI下6条,3G/4G下2~3条。