2.1 进程和线程
进程
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。
在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。
线程
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
2.2 并行和并发
- 并发(concurrent)是同一时间内对应多件事情
- 并行(parallel)是同一时间动手做多件事情
例子
- 妈妈做饭、打扫卫生、给孩子喂奶,她一个人轮流交替做很多事情,这时就是并发
- 妈妈雇了保姆,她们一起做这些事情这时候既有并发,也有并行(这时回产生竞争,例如锅只有一口,一个人用锅时,另一个就得等待)
- 雇了3个保姆,一个专做饭、一个打扫卫生、一个喂奶、互不打扰,这是并行。
同步和异步
- 同步:需要等待结果返回,才能继续运行就是同步
- 异步:不需要等待结果返回,就能继续运行就是异步
注意: 同步在多线程中还有另外一层意思,就是让多个线程步调一致
结论(多线程的好处)
- 比如在项目中,视频文件需要转换格式等操作比较费时,这时开一个新线程处理视频转换,避免阻塞主线程
- tomcat 的异步 servlet 也是类似的目的,让用户线程处理耗时较长的操作,避免阻塞 tomcat 的工作线程。
- ui程序中,开线程进行其他操作,避免阻塞ui 线程
注意: 需要在多核CPU才能提高效率,单核仍然是轮流运行,是并发的。单核情况下,多线程进行上下文切换可能更加耗时。
结论
- 单核 cpu 下,多线程不能实际提高程序运行效率,只是为了能够在不同的任务之间切换,不同线程轮流使用cpu,不至于一个线程总占用 cpu,别的线程没法干活
- 多核cpu可以并行跑多个线程,但能否提高程序运行效率还是要分情况的
- 有些任务,经过精心设计,将任务拆分,并行执行,当然可以提高程序的运行效率。但不是所有计算任务都能拆分(参考后文的【阿姆达尔定律】)
- 也不是所有任务都需要拆分,任务的目的如果不同,谈拆分和效率没啥意义
- IO操作不占用CPU,只是我们一股拷贝文件使用的是【阻塞IO】,这时相当于线程虽然不用CPU,但需要一直等待IO 结束,没能充分利用线程。所以才有后面的【非阳塞IO】和【异步IO】优化