JavaEE 初阶(进程)

一、操作系统

操作系统是计算机中的一个重要软件。
操作系统是一个搞管理的软件:

  • 管理各种硬件设备
  • 给各种应用程序提供一个稳定的运行环境,
    这些应用程序在运行中,即使有一个应用程序发生bug崩溃了,也不会影响其他应用程序的执行。

操作系统中的重要概念:进程

• 运行起来的程序就叫进程。
站在操作系统的视角,如何管理进程?

  1. 先描述
    使用结构体,描述出进程的核心属性,
    进程控制块(PCB),非常大的结构体,有很多个属性。

  2. 再把多个进程组织起来
    比如:Linux这样的操作系统,使用链表这样的方式,把每个PCB串一起。

操作系统本身也是一个软件,也是由一系列指令构成的,在启动时,CPU依次执行操作系统上的这些指令(引导操作系统起来)

• 所有的软件本质上都是靠CPU来执行的,CPU具体执行哪些指令,一定程度上受操作系统的影响

  1. 文件描述符
    进程在运行过程中,很多时候需要和硬盘这个硬件设备进行交互。
    硬盘上的数据,就是以文件的形式来组织的。
    进程在读写文件的时候,就需要打开文件,每个打开的文件相关的信息保存到文件描述符中,文件的每一项都对应着打开了的一份文件。

操作系统中,会把很多资源抽象成文件来表示,所以“文件”不只是硬盘上的类
例:网卡,操作系统管理网卡的时候,就是当作“文件”一样来管理

二、进程的运行

进程的运行,也会依赖到硬盘、网卡等相关硬件设备

进程运行,执行指令,都是靠CPU的。

  1. 进程是操作系统中,负责分配CPU的基本单位。
    分时复用:把一个单位时间,分成很多份,分别执行不同进程的指令
    第一份,执行进程1指令
    第二份,执行进程2的指令……
    因为CPU的运行速度是特别快,所以在切换的过程中,人眼很难察觉出变化了,像同时执行一样。

    • 把一个CPU核心上,按照分时复用,执行多个进程,就叫“并发执行”
      多个进程在一个CPU核心上在不同单位时间内执行

    • 多个CPU核心上,同时执行多个进程 称为“并行执行
      多个进程多个CPU核心同时执行

  2. 进程状态,

    • New(新建)
    • RUNNABLE(可运行)
    • BLOCKED(阻塞)
    • WAITING(等待)
    • TIMED_WAITING(超时等待)
    • TERMINATED(终止)
      • 进程有多种状态,下面是两个典型
        1)就绪状态 → 随时可以到CPU上执行
        2)阻塞状态 → 进程当前不适合到CPU上执行
  3. 进程有优先级
    为了保证需要大量CPU资源能的正常执行

  4. 进程的上下文
    因为有进程调度,一个进程执行一会,就会让出CPU,这期间CPU执行它会保存上次执行的状态,多进程继续执行

进程在CPU中运行的过程中
CPU上的各种寄存器,就保存了当前进程运行的“中间状态
寄存器上关于进程的信息,存放在内存中(PCB自己也会有对应空间)
恢复时:把PCB中刚才保存的属性,填回CPU的寄存器。

  1. 进程的记账信息
    统计功能,统计每个进程在CPU上运行了多久
    如果发现某个进程 很久没有吃到CPU资源,就会给它资源倾斜
    一点之后,防止这个进程饿死

new(新建),runnable(可运行)、blocked(阻塞)、waiting(等待)
timed_waiting(超时等待) terminated(终止)

三、多线程

  • 进程整体是一个比较“重”的概念

  • 创建进程/销毁进程开销比较大

  • 为了解决上述问题,引入线程,轻量级进程(创建销毁开销小)

    • 每个进程都相当于一个要执行的任务
    • 每个线程也是一个要执行的任务
  1. 进程包含线程
    每个进程中,都会包含一个或多个线程

  2. 进程是操作系统资源分配的基本单位
    进程内部所包含的多个线程之间,会共享上述的内存资源和硬盘资源,网络带宽。

进程创建,需要申请资源
进程的销毁,需要释放资源
→ 重量级事物,(代价大,时间消耗)

  • 对于线程来说,只是第一个线程创建的时候(和进程一起创建)申请资源,后续再创建线程,不再手动到资源申请操作(内核少,快)
  • 只有所有的线程都销毁(进程销毁)才会释放资源,单个进程销毁某个线程,也不会释放资源。
  • 可以理解为:在进程创建的时候给线程创建了一次资源,后续线程的创建和销毁都在这一层,只有进程被销毁这一次资源才会被回收

关于线程的调度,是随机的,我们的程序是感知不到,也干预不了。

那怎么提高效率?

引入多个线程, 确实可以提升效率, 但是资源一旦 就那么多,引入过多线程会使上下文切换开销增长,因为调度开销会拖累程序的性能。
而且其中一个线程抛出异常,会带走整个进程,所有的线程都无法运行
如果及时捕获,也不一定 终导致进程终止。

  • 创建第一个线程
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("hello");
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // throw new RuntimeException(e); // 处理异常的手段:抛出异常,导致程序异常终止
            break;
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start(); // 开启线程
    }
}

其中 Thread.sleep(); 会休眠
例:Thread.sleep(0); 这里是 让此线程放弃当前CPU资源,给别的线程用
run() 方法内,Thread.sleep()会抛出异常,但无法 throws,只能使用 try{} catch{}捕获。

  • 每个线程,调度顺序是随机的,无法预测。“抢占式执行”

创建线程的方法:

  1. 继承 Thread,重写 run

  2. 实现 Runnable 接口,重写 run
    例:

    • Runnable runnable = new MyRunnable();

    • Thread t = new Thread(runnable);

      class MyRunnable implements Runnable {
          @Override
          public void run() {
              System.out.println("我自己的 Runnable 的 run 方法");
          }
      }
      public class Deano01 {
      
          public static void main(String[] args) {
              Runnable r1 = new MyRunnable();
              Thread t1 = new Thread(new MyRunnable());
              Thread t2 = new Thread(r1);
              t1.start();
              t2.start();
          }
      }
    
      class MyThread extends  Thread{
          @Override
          public void run() {
              System.out.println("我自己的 Thread 的 run 方法");
          }
      }
      public class Deano01 {
      
          public static void main(String[] args) {
              // 1. 自己实现一个自己的Threa类
              Thread t = new MyThread();
              t.start();
              // 2. 使用 lamabda 表达式
              Thread t1 = new Thead(() -> {
                  System.out.println("我自己的 Thread 的 run 方法");
              });
          }
      }
    

    这个接口中,只有一个无参返回值的 run 方法
    可以使用 lambda 表达式 () -> { 要执行的代码 }
    在括号里没有参数!

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐