java中的进程的详细解析

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. 进程是操作系统资源分配的基本单位

    进程内部所包含的多个线程之间,会共享 上述的内存资源和硬盘资源,网络带宽。

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

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

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

那怎么提高效率?

引入多个线程 , 确实可以提升效率, 但是资源一旦 就那么多,引入过多线程会使上下文切换开销增长,因为调度开销会拖累程序的性能。

而且其中一个线程抛出异常 ,会带走整个进程 ,所有的线程都无法运行

如果及时捕获,也不一定 终导致进程终止。

  • 创建第一个线程
java 复制代码
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);

    java 复制代码
      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();
          }
      }
    java 复制代码
      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 表达式 () -> { 要执行的代码 }

    在括号里没有参数!

相关推荐
J2虾虾13 分钟前
C 语言 void 完全用法
c语言·开发语言
码语智行19 分钟前
地图上图、空间拓扑查询示例
java·arcgis
会Tk矩阵群控的小木30 分钟前
基于Python的iMessage短信群发与社媒多账号统一管理系统实现
开发语言·windows·python·新媒体运营·开源软件·个人开发
程序员黑豆32 分钟前
AI全栈开发 - Java:变量
java·前端·ai编程
我是一颗柠檬33 分钟前
【Java项目技术亮点】分库分表+数据路由策略:单表5000万后的架构升级方案
java·开发语言·分布式·架构
wu_ye_m35 分钟前
学习c语言第35天 函数声明和定义
c语言·开发语言·学习
布朗克16842 分钟前
25 IO流高级操作——序列化、NIO与Files工具类
java·数据库·io·nio
njsgcs42 分钟前
c# solidworks 创建装配体工程图+bom
开发语言·c#·solidworks
小研说技术1 小时前
Spring AI实现rag流程(简易版)
java·后端
亓才孓1 小时前
【本地项目引用外部库的类,想修改字段遇到的请缓存的问题】
java·maven