进程
进程是运行着的程序,是程序在操作系统的一次执行过程,进程是操作系统分配资源的基本单位。
启动一个java程序,操作系统就会创建一个java进程
进程也可以看作一个程序的实例,大部分程序可以运行多个实例进程,比如记事本,有的程序只能启动一个实例进程,如果qq音乐。
线程
线程可以理解为一个进程的执行实体,多个线程组成一个进程,是操作系统调度资源的基本单位。
一个线程就是一个指令流,是真正可以运行在cpu上的执行单元。
对比
- 进程基本相互独立,线程存在进程之内。
- 进程拥有共享的资源,供内部线程共享。
- 进程通信:同一台计算机的进程通信,称为IPC(Inter-process communication);不同计算机通信需要经过网络,遵循例如HTTP的协议。
- 线程通信:共享进程的内存,比如多个线程可以访问同一共享变量。
- 线程更加轻量,线程上下文切换成本往往低于进程上下文切换。
并行与并发
单核cpu,线程是串行的,但是任务调度器将cpu时间片分给不同线程。给人一种微观串行,宏观并行的感觉。
线程轮流使用cpu,这就是并发(concurrent)
并行(parallel):多核cpu,每个核都可以调度线程,这时线程是并行的。
下图中,即有并行(同一时刻,两个core调度不同的线程),也有并发(4个线程轮流地使用core)。
同步与异步
同步:需要等待结果返回,才能继续运行
异步:不需要等待结果返回,就能继续运行。多线程可以让方法变成异步。
例如如下代码就是异步的,主线程和新线程一起启动,主线程无需等待另一个线程结束就可以执行打印”do“。
@Slf4j(topic = "c.Async")
public class Async {
public static void main(String[] args){
new Thread(() -> {
String s = "do it !!!";
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(s);
}).start();
log.debug("do");
}
}
应用场景举例:
例如项目中的视频文件格式转换,需要耗费大量时间,这时候就需要新开一个线程处理视频文件格式转换,避免阻塞了主线程。
提高效率
多线程的目的是为了充分利用多核CPU。
比如我们要执行三次计算,分别耗时10ms,11ms,12ms。如果我们可以开三个线程分别运行,那我们理论上的运行时间取决于最大用时,也就是12ms。
但如果是单核cpu,串行用时10+11+12 = 33ms,如果这时开三个线程,时间肯定大于33ms,因为cpu是单核的,实际上还是在串行执行这些线程,还需要上下文切换的时间,更加耗时。
所以,单核cpu下的多线程实际上并不会提高运行效率,而是可以再不同任务间切换,避免一个线程总占用cpu。