进程(process) => 任务(task) ~
双击 .exe 文件的时候, 操作系统就会读取这个可执行文件中的代码和数据, 放到内存中, 并且创建出一个进程来执行里面的代码
一个操作系统, 工作的时候里面本来就有很多的进程
这些进程各自在做各自的事情, 互相不干扰
进程的重要特点: 独立性
某个进程出现问题的时候, 只是当前进程崩溃了, 不会干扰到其他的进程
例如:
编译运行java程序
- javac 命令进行编译
- java 命令进行运行
当输入 javac, 或者 java 这些命令的时候, 其实操作系统也是创建出了一个进程, 去执行对应的编译或者运行的任务
实现的在线 OJ 系统中的编译运行代码, 这个过程就需要用到多进程编程
网页把用户输入的代码通过 HTTP 请求发送给服务器, 服务器就需要创建出一个 javac 进程, 通过 javac 进程把这段代码给编译成 .class 文件
再创建出一个java 进程, 通过 java 进程来执行这个 .class 并运行里面的测试用例
创建 javac , 创建 java 这些进程去编译执行代码的过程其实就是在进行 "多进程编程"
一个进程移动的时候默认大开了3个文件
标准输入 System.in
标准输出 System.out
标准错误 System.err
为啥操作系统要有多进程?
目的就是为了能够同时(并发)执行多个任务, 多进程是实现并发编程的一种重要方式
其实, 创建一个进程, 是一个开销比较大的事情(进程的独立性, 每一个进程都需要有自己的独立的内存空间[虚拟地址空间])
正因为如此, 进行频繁创建销毁进程就是一个比较低效的事情
为了进一步的提高效率, 引入了"线程"
线程也叫做"轻量级进程"
每次创建一个新的线程, 并不需要重新分配那么多资源(虚拟地址空间)
而是和前面的线程共用同一组资源(虚拟地址空间)
实际上在操作系统中, 进程线程这样的概念是同时存在的
是一个"包含关系"
一个进程中可以包含一个线程, 也可以包含多个线程,
如果包含多个线程这种, 此时这多个线程之间就共享同一份内存资源(虚拟地址空间)
资源管理:
CPU, 内存, 磁盘, 带宽…计算机的资源
操作系统执行一个程序的时候, 就需要给这个对应的进程分配一定的CPU(让这个进程有一定的时间能去 CPU 上执行命令), 分配一定的内存 (需要加载 .exe 的指令和数据), 以及磁盘等其他的资源
调度执行:
计算机的 CPU 是比较有限的, 只有几个, 而进城/线程数目是很多的
Java中进行多线程的操作是比窘粗糙的,但是够用了, 可以使用Runtime这样的类完成进程的创建
注意,Runtime比较特殊,咱们在使用的时候,并不需要去创建新的实例,而是使用线程有的实例就可以了。
一个Java程序中,Runtime的实例只有一个,没有其他的,这就叫做单例模式
Process process= Runtime.getRuntime().exec(cmd);
exec 这个方法生成的进程, 就是新进程, 正在执行 exec 方法的这个进程就是旧进程
当创建好这个进程之后, 新的进程就和当前进程是一个并列的关系
两者就会 “并发” 式的执行
int exitCode = process.waitFor();
进程与进程之间先后顺序是不确定的因此就必须等待进程结束waitFor 这个方法, 就会阻塞式的等待, 父进程执行到 waitFor 的时候就会暂时停下来, 就不会继续往下走了, 直到子进程执行完毕后退出之后, 父进程的 waitFor 方法才会返回, 获取到紫禁城的退出码