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

    在括号里没有参数!

相关推荐
烟雨江南aabb9 小时前
Python第六弹:python爬虫篇:什么是爬虫
开发语言·爬虫·python
沐知全栈开发9 小时前
Servlet 文件上传详解
开发语言
Mr_sst9 小时前
Codex 部署、使用教程 & Vibe Coding 实战指南
java·ai·语言模型·chatgpt·ai编程
无限进步_9 小时前
【C++】C++11的类功能增强与STL变化
java·前端·数据结构·c++·后端·算法
basketball6169 小时前
C++ iostream 完全指南:从 cin/cout 到流式编程的奥秘
开发语言·c++
日月云棠9 小时前
JAVA数据结构与算法 - 基础:常用集合简述
java·算法
噢,我明白了9 小时前
MyBatis-Plus的引入和配置
java·tomcat·mybatis
SilentSamsara9 小时前
运算符重载:让自定义对象支持 +、[]、in 操作
开发语言·python·算法·青少年编程·pycharm
threelab9 小时前
Three.js 3D 热力图效果 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器