1 进程 & 线程
1.1 背景
最初的计算机只能接受一些特定的指令,用户每输入一个指令,计算机就做出一个操作。当用户在思考或者输入时,计算机就在等待。这样效率非常低下,在很多时候,计算机都处在等待状态。
批处理操作系统
把一系列的指令写下来,形成一个清单一次性交给计算机,一次性交给计算机。用户将多个需要执行的程序写在磁带上,然后交由计算机去读取并逐个执行这些程序,并将输出结果写在另一个磁带上。
批处理系统一定程度上提高计算机的效率,但是指令执行仍然是串行执行,一个指令须等待上一个指令执行完才能开始执行,其中可能有IO、网络等原因阻塞,导致后续指令全部等待影响效率。
1.2 进程
为解决批处理系统的问题,提出进程的概念,把一系列的的计算任务组装在一起形成一个进程,操作系统分配独立的地址空间,每个个进程相互之间独立,操作系统采用进程+时间片轮转的方式执行,在某个进程阻塞时,可以切换到另一个进程执行,实现让多个进程可以在一段时间内并发执行,但事实上对于单核CPU来说,同一时间只有一个任务在执行。
进程:是程序执行的一次过程,是操作系统分配和管理资源的基本单位,拥有独立的地址空间,多个进程相互之间独立。
时间片轮转:CPU为每一个进程分配一个时间段,称为时间片,在该时间片内执行该进程的计算任务,如果时间片内未执行完,则暂停这个进程的运行,并且CPU分配给另一个进程(这个过程叫做上下文切换)。如果进程在时间片结束前阻塞或结束,则CPU立即进行切换,不用等待时间片用完。
1.3 线程
虽然进程的出现,使得操作系统的性能大大提升,但是一个进程在一段时间只能做一件事情,如果一个进程有多个子任务时,只能逐个得执行这些子任务,很影响效率。进而提出线程,将进程内多个子任务分派给子线程去执行,操作系统基于线程任务去分配CPU执行。
线程:进程内一个子任务的执行路径,线程是CPU调度和分派的基本单位,共享进程的地址空间。
进程和线程的提出极大的提高了操作系统的性能。进程让操作系统的并发性成为了可能,而线程让进程的内部并发成为了可能。
1.4 进程和线程的区别
- 进程单独占有一定的内存地址空间,所以进程间存在内存隔离,数据是分开的,数据共享复杂但是同步简单,各个进程之间互不干扰;而线程共享所属进程占有的内存地址空间和资源,数据共享简单,但是同步复杂。
- 一个进程出现问题不会影响其他进程,不影响主程序的稳定性,可靠性高;一个线程崩溃可能影响整个程序的稳定性,可靠性较低。
- 进程的创建和销毁不仅需要保存寄存器和栈信息,还需要资源的分配回收以及页调度,开销较大;线程只需要保存寄存器和栈信息,开销较小。
- 进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位,即CPU分配时间的单位 。
1.5 上下文切换
上下文切换(有时也称做进程切换或任务切换)是指CPU从一个进程(或线程)切换到另一个进程(或线程)。上下文是指某一时间点CPU寄存器和程序计数器的内容。
程序计数器:用于表明指令序列中 CPU 正在执行的位置,存的值为正在执行的指令的位置或者下一个将要被执行的指令的位置.
寄存器:cpu内部的少量的速度很快的闪存,保存计算的缓存数据
当发生上下文切换时需要保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态
上下文切换通常是计算密集型的,意味着此操作会消耗大量的CPU时间,故线程也不是越多越好。
2 Thread & Runnable
2.1 线程的创建
public class ThreadTest {
public static void main(String[] args) {
//实现Runnable的方式
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},"thread1");
//使用继承Thread的方式
new Thread("thre