一、多线程知识的简单介绍
1、进程、线程、任务
1.1、什么是进程
进程是指在系统中正在运行的一个应用程序。每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
比如同时打开酷狗、迅雷两款软件,系统就会分别启动2个进程。
通过电脑上的“活动监视器”可以查看Mac系统中所开启的进程。
在苹果手机上双击home键也可以看到系统中正在运行的进程。
1.2、什么是线程
1个进程要想执行任务,必须要有线程(每个进程至少要有1条进程)。线程是进程的基本执行单元,1个进程(应用程序)的所有任务都是在线程中执行的,比如使用酷狗播放音乐、使用迅雷下载电影,都需要在线程中执行。
1.3、什么是任务
应用程序中需要做的事情都抽象为任务。比如酷狗播放音乐的任务、迅雷下载文件A的任务、迅雷下载文件B的任务。
任务需要放置在线程中执行,可以放置多个任务到一个线程中,但是1个线程中任务的执行是串行的。串行的意思就是说,如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务,也就是说,在同一时间内,1个线程只能执行1个任务。
比如在迅雷进程中的线程2中,有3个下载任务(分别下载文件A、文件B、文件C),因此也可以认为线程是进程中的1条执行路径。
2、多线程
综上,一个应用程序就是一个进程,进程中想要执行任务就需要创建线程,然后把任务放置在线程中执行,一个进程至少有一个线程,一个线程中可以放置有多个任务,但是同一个线程中的任务的执行是串行的,是一个接一个执行的。
CPU会对线程进行调度,CPU调度到哪个线程,就会执行该线程中的任务。同一时间,CPU只能处理1条线程,也就是说,只有1条线程在工作(执行任务)。1个进程中可以创建开启多条线程,每条线程中放置不同的任务,如果CPU调用线程的时间足够快,也就是说CPU快速地在多条线程之间切换调度,那就造成了多个线程并发执行的假象,也就是感觉多个文件在同时下载,这是创建多个线程的好处之一。
创建多个线程的第二个好处就是,将比较耗时的任务放到其他线程中,不影响主线程中任务的执行。
上面说到过,一个进程中至少有一个线程,其实这个线程称之为主线程或UI线程,当一个iOS程序运行后,这个程序就是一个进程,在这个进程中默认会开启1条线程,这个至少存在的主线程的主要作用就是显示或者刷新UI界面、处理UI事件(比如点击事件、滚动事件、拖拽事件等)。因为用户使用手机上的软件,手指会在屏幕上频繁的做很多操作,因此主线程要做的事情其实很多的,刚刚上面提到了,在同一个线程中的任务是串行执行的,只有当上一个任务执行完成之后,才会执行下一个任务,如果将其他耗时的任务放置在主线程中,那就会让接下来的UI事件处理不及时,给用户很“卡顿”的感觉。解决这种卡UI线程的问题的方式就是再创建一个线程,将这种耗时的任务放置在其他线程中。
综上所述,使用多线程的情景是这样的,首先如果出现比较耗时的任务操作,那么不能将这类任务放置在主线程中,需要另外创建开启额外的线程,这种额外的线程,称之为“子线程”。然后如果这类耗时任务比较多的情况下,与其将它们统统放置在同一个子线程中,让这些耗时任务一个接一个被执行,还不如创建开启多个子线程,每个子线程中只放置一个耗时任务,当CPU快速地在多个线程之间切换调度时,会发现多个耗时任务同时在执行,可以提高程序的执行效率。既然如此,是不是子线程开得越多越好?秉持“一个子线程中就一个任务”的做法呢?显然不行。
开启多个子线程,即多线程的好处:(1)能适当提高程序的执行效率;(2)能适当提高资源利用率(CPU、内存利用率)。
开启多个子线程,即多线程的缺点:(1)开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能。(2)线程越多,CPU在调度线程上的开销就越大,CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源。(3)进程中开启的线程太多了,每个线程被调度执行的频次就会降低,线程的执行效率也会降低,包括主线程被调度的频率也会降低,也相当于是造成了主线程的卡顿。(4)多线程会涉及到线程之间的通信、线程之间的数据共享,如果子线程开启太多,程序设计会更加复杂。
综上所述,有三种情况会造成UI主线程的卡顿,即用户使用软件感觉很卡、很不爽,原因:
(1)把一些耗时的任务,放在了UI主线程中
(2)开启的子线程太多了,导致UI主线程被CPU调度的频率下降了
(3)CPU、内存这些配置太低了,就算不做耗时操作,频繁的操作UI界面,都让CPU够呛了