目录
- 进程
- 系统管理进程
- 系统操作进程
- 进程控制块PCB关键属性
- cpu对进程的操作
- 进程调度
- 线程
- 线程与进程
- 线程资源分配
- 线程调度
- 线程与进程区别
- 线程简单操作代码
- 创建线程
- 查看线程
进程
进程是操作系统对一个正在运行的程序的一种抽象,可以把进程看做程序的一次运行过程;
同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。
系统管理进程
- 先描述一个进程:
使用结构体(因为操作系统主要由c语言写成),再描述出进程的核心属性即进程控制块PCB(Process Control Block)。 - 把多个进程组织起来:
使用数据结构组织起来,Linux使用链表来组织。
系统操作进程
- 进程的创建:创建一个PCB,初始化各个属性,加入到数据结构中。
- 进程的销毁:在数据结构中找到并删除。
- 查看进程列表:遍历查找到进程,现显示关键数据。
进程控制块PCB关键属性
- pid (进程id):相当于身份证,每个进程不一样。
- 一组内存指针:指向进程执行的指令,依赖。
- 文件描述符表:进程运行时,多数要与硬盘进行交互,硬盘储存数据的方式是通过文件存储,而文件的信息就保存在文件描述符表中。操作系统回将很多资源抽象为文件。
- 进程状态:两个主要的进程状态:1.就绪状态:进程随时能到CPU上执行,2.阻塞状态:进程当前不适合在CPU上执行。
- 进程优先级:优先级越高,分配的CPU资源越多。
- 进程的上下文:进程的调度原理,会使得进程在执行了一会之后会失去CPU,CPU再次执行回来时,要沿着上次结束状态执行。
而进程在CPU上运行时,床铺上的各种寄存器就会记录当前进程的中间状态,
将寄存器的各种记录保存到pcb对应属性,下次执行时又返回给对应寄存器就恢复了进程上下文。 - 进程的记账信息:统计每个进程在CPU上执行了多久。如果该进程长时间没分配到CPU资源,就会给这个进程倾斜一些CPU资源。
cpu对进程的操作
CPU对进程的操作是 分时复用。
分时复用就是指:把一份时间分为多份,每份时间执行对应的进程。由于CPU运行速度快,让进程切换的时间超过了肉眼反应。
并发执行:一个CPU核心上按照分时复用执行进程。
并行执行:多个CPU核心执行多个进程。
现代CPU都是两者兼备。
由于代码无法区分,平时就将两者合起来叫做“并发”
进程调度
进程调度就是指操作系统在并发执行进程时,进程之间的相互切换。
而上面PCB中的进程状态,进程优先级,进程上下文,进程记账信息就是支持进程调度的。
线程
线程:一个线程就是一个 “执行流”. 每个线程之间都可以按照顺讯执行自己的代码。就相当于是一个轻量级的进程。
线程与进程
线程与进程的关系是包含关系,每个进程中至少要有一个线程。
相当于周计划(进程)与日计划(线程)的关系。
线程资源分配
每个进程的创建需要申请资源,销毁需要释放资源。
而在一个进程中只有第一个线程创建需要申请资源,所有线程销毁完才需要释放资源。
而在一个进程中所有线程共享资源,这样会带来如果一个线程出问题,可能所有线程就出问题了。就像一个线程中抛出一个异常没处理,就将整个进程中的线程全部搞挂。
这样的好处是开销小,效率高,但是如果线程过多也会使线程调度开销大,影响效率。
线程调度
操作系统操作线程(一个进程内)也和进程一样有并发执行和并行执行。
线程也有线程状态,线程优先级,线程上下文,线程记账信息(与上诉进程的介绍一样,只需把进程改为线程即可)。
而内存指针和文件描述符表是一个进程中所有线程共享的。
线程与进程区别
- 进程是系统进行资源分配和调度的一个独立单位,线程是程序执行的最小单位。
- 进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈。
- 由于同一进程的各线程间共享内存和文件资源,可以不通过内核进行直接通信。
- 线程的创建、切换及终止效率更高。
线程简单操作代码
创建线程
创建线程有两种方式:
- 使用类继承Thread类,重写run方法。在主函数中创建好对象后调用start方法就创建好了一个线程。
class MyThread extends Thread {
@Override
public void run() {
//写代码
}
}
public class Demo1 {
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
}
}
- 实现Runnable接口,重写run方法,通过Thread创建对象时,将实现Runnable接口的类对象传到构造函数中,在调用start方法。
class MyRunnable implements Runnable {
@Override
public void run() {
}
}
public class Demo2 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
- 还可以使用匿名内部类
Thread thread = new Thread() {
@Override
public void run() {
//写代码
}
}
Thread thread = new Thread(new Runnable) {
@Override
public void run() {
//写代码
}
}
- lambda 表达式
Thread thread = new Thread ( () -> {
//写代码不用重写run方法
});
Thread thread = new Thread( (new Runnable) ->{
//写代码不用重写run方法
});
查看线程
在当前电脑上看由Java写的线程可以找到安装使用的JDK写的bin目录里面的Jconsole.exe程序。
运行这个程序里面就可以看当前的线程。