• JavaEE初阶——计算机是如何工作的


    目录

    一,冯诺依曼体系

    二,CPU基本工作流程

    三,进程

     1.什么是进程/任务

     2. PCB——进程控制块抽象(Process Control Block)

    (1).pid 进程的身份标识

    (2).内存指针

    (3).文件描述符表

    (4).进程状态

    (5).进程优先级

    (6).进程上下文

    (7).进程信息

     3.创建进程/销毁进程

     4.进程的“属性”

    (1).进程状态

    (2).进程优先级

    (3).进程上下文

    (4).进程记账信息

    (5).并发和并行

     5.虚拟地址空间

     6.进程间通信

    四,线程

    五,进程和线程的区别

    六,线程的使用

    1.利用extends继承Thread类

    2.利用implements实现Runnable接口

    3.匿名内部类创建Thread子类对象

    4.匿名内部类创建 Runnable 子类对象

    5.lambda 表达式创建 Runnable 子类对象

    3.线程的方法

    (1).start()——启动一个线程

    (2).join()——等待一个线程


    一,冯诺依曼体系

    CPU 中央处理器(center process unit): 进行算术运算和逻辑判断.(ALU+CU+寄存器+时钟)
    存储器: 分为外存和内存, 用于存储数据(使用二进制方式存储)
    输入设备: 用户给计算机发号施令的设备:网卡,手写笔
    输出设备: 计算机个用户汇报结果的设备.

    针对存储空间
    硬盘 > 内存 >> CPU
    针对数据访问速度
    CPU >> 内存 > 硬盘

    二,CPU基本工作流程

    程序=指令+数据 / CPU=ALU+CU

    ALU(算数逻辑单元):CPU的执行单元,是所有中央处理器的核心组成部分,由“与门”和“或门”构成,算术逻辑单元的运算主要是进行二位元算术运算,如加法、减法、乘法。

    CU(控制单元):负责程序的流程管理

    1.取指令

    即将一条指令从主存储器中取到的指令寄存器过程。

    2.指令译码阶段

    取出指令后,指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分出不同的指令类别以及各种获取操作数的方法。 

    3.执行指令阶段

    具体实现指令的功能。CPU的不同部分被连接起来,以执行所需的操作。

    4.访存取数阶段

    根据指令需要访问主存、读取操作数,CPU得到操作数在主存中的地址,并从主存中读取该操作数用于运算。部分指令不需要访问主存,则可以跳过该阶段。 

    5.结果写回阶段

    作为最后一个阶段,结果写回阶段把执行指令阶段的运行结果数据“写回”到某种存储形式。

    在指令执行完毕、结果数据写回之后,若无意外事件(如结果溢出等)发生,计算机就从程序计数器中取得下一条指令地址,开始新一轮的循环,下一个指令周期将顺序取出下一条指令。 

    1. CPU 中的 PC 寄存器,是决定 CPU 要执行哪条指令的关键;
    2. 指令是由 动作 + 操作对象组成
    3. CPU 眼中只有指令,没有其他的概念

    三,进程

    1.什么是进程/任务

    简单来说,可以把进程看做程序的一次运行过程;

    同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。

    2. PCB——进程控制块抽象(Process Control Block)

    每一个PCB对象,就代表一个正在运行的程序,即进程 ,其包含

    (1).pid 进程的身份标识

    一个主机,同一时刻,这些进程的pid是唯一的,通过pid来区分一个进程

    (2).内存指针

    一个可执行文件,双击运行后,操作系统把文件中的核心数据加载到内存中

    内存空间分配:存放指令+存放数据+维护运行状态

    (3).文件描述符表

    用于记录当前进程中打开的文件

    (4).进程状态

    (5).进程优先级

    (6).进程上下文

    (7).进程信息

    3.创建进程/销毁进程

    创建一个进程,本质上就是创建PCB,并且加入到链表上

    1.创建PCB

    2.给进程分配资源(内存/文件),赋值到PCB中

    3.把PCB插入到链表中

    销毁一个进程,本质上就是从链表是删除对应的PCB节点

    1.把PCB从链表上删除

    2.

    4.进程的“属性”

    (1).进程状态

    分为就绪和阻塞,一旦进程阻塞,则无法被调度到CPU上执行

    (2).进程优先级

    系统调用的时候,就会根据优先级,来给进程进行安排时间,当创建进程的时候,可以通过一些系统调用来干预优先级

    (3).进程上下文

    相当于存档与读档,即将运行中的值存储在CPU的寄存器中,下次在由此进行

    (4).进程记账信息

    记录每个进程在CPU上执行了多久,统计信息

    (5).并发和并行

    并行:某一个时刻,多个程序同时运行
    并发:某一个CPU,   cpu来回切换多个程序

    但对于肉眼来说,无法看出差别

    5.虚拟地址空间

    虚拟地址空间会给每个进程安排一些内存资源,通过专门的设备MMU来完成虚拟地址到物理地址之间的映射,增加了隔离性,使进程稳定

     6.进程间通信

    添加一个多个进程都能访问到的公共资源,然后基于公共资源来交换数据,使得进程间进行交互

    四,线程

    使用多线程:

    1.能够充分利用上多核CPU,能够提高效率

    2.创建第一个线程的时候,需要申请资源,后续再创建新的进程,都是共用同一份资源       

    (节省了申请资源的开销)

       销毁线程的时候,也是销毁到最后一个的时候,才真正释放资源

    五,进程和线程的区别

    1.进程是资源分配的基本单位 ,线程是调度执行的基本单位

    2.进程包含线程

    3.线程比进程更轻量,创建快,销毁也快

    4.同一个进程的多个线程之间共用同一份内存/文件资源 ,而进程与进程间是独立的

    六,线程的使用

    1.利用extends继承Thread类

    1) 继承 Thread 来创建一个线程类.

    class MyThread extends Thread {
      @Override
      public void run() {
        System.out.println("这里是线程运行的代码");
     }

      try{

           Thread.sleep(1000);//休眠1000ms.即1s

           } catch(InterruptedException){

            e.printStackTrace();

           }

    }

     2) 创建 MyThread 类的实例

    MyThread t = new MyThread();//非进程

    3) 调用 start 方法启动线程

    t.start();//创建实例并不会产生进程,使用后才会产生 

    抢占式执行:当启动另外一个线程,新的线程是一个单独的执行流,和现有线程的执行流不相关,并发+并行执行,但是操作系统调度现成的时候是一个“随机”的过程,所以执行的时候也会产生随机

    2.利用implements实现Runnable接口

    1) 实现 Runnable 接口

    class MyRunnable implements Runnable{

        public void run(){

        System.out.println("这里是线程运行的代码");

        try{

           Thread.sleep(1000);//休眠1000ms.即1s

           } catch(InterruptedException){

            e.printStackTrace();

           }

       }

    }

     2) 创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.

    Thread t = new Thread(new MyRunnable());

    3) 调用 start 方法

    t.start(); 

    1.把任务从线程提取出来,把线程要干的活和线程本身分开了

    2.如果要搞多个线程干相同的事情,

    3.匿名内部类创建Thread子类对象

    Thread t1 = new Thread() {
      @Override
      public void run() {
        System.out.println("使用匿名类创建 Thread 子类对象");
     }
    };

    4.匿名内部类创建 Runnable 子类对象

    Thread t2 = new Thread(

    new Runnable() {
      @Override
      public void run() {
        System.out.println("使用匿名类创建 Runnable 子类对象");
      }
    }

    );

    5.lambda 表达式创建 Runnable 子类对象

    Thread t3 = new Thread(

    () -> System.out.println("使用匿名类创建 Thread 子类对象")

    );


    Thread t4 = new Thread(

    () -> {
      System.out.println("使用匿名类创建 Thread 子类对象");
    }

    );

    3.线程的方法

    (1).start()——启动一个线程

    覆写 run 方法是提供给线程要做的事情的指令清单

    而调用 start 方法, 才真的在操作系统的底层创建出一个线程.

    (2).join()——等待一个线程

    t1.join();

    t2.join();

    此处t1和t2是并发执行,而不是t1执行完后才继续执行

  • 相关阅读:
    Ubuntu工具-2 OBS Studio
    题目0148-总最快检测效率
    1997-2017年各省能源投入数据(万吨标准煤)
    APP自动化之weditor工具
    Elasticsearch索引别名:管理与优化数据访问
    Jmeter高效组织接口自动化用例
    上海亚商投顾:沪指失守3200点 房地产板块逆市走强
    配对交易之统计套利配对:协整(cointegration)
    算法|每日一题|求一个整数的惩罚数|回溯
    Flask 自建扩展
  • 原文地址:https://blog.csdn.net/weixin_63056061/article/details/126314798