进程/线程/PCB

进程:正在运行中的程序(进程是驻留在内存中的)

  • 是系统执行资源分配和调度的独立单位
  • 每一个进程都有属于自己的存储空间和系统资源
  • 注意:进程A 和 进程B 的内存独立不共享

使用jdk自带的工具,jconsole查看当前Java进程中的所有线程。

        new Thread对象,操作不创建线程。(说的线程指的是 系统内核里的PCB)

        调用start才是创建PCB,才是有货真价实的线程的。 

线程:进程中的单个顺序控制流,也可以理解成是一条执行路径。

  • 单线程:一个进程中包含一个顺序控制流(一条执行路径)
  • 多线程:一个进程中包含多个顺序控制流(多条执行路径)
  • 在java中:线程A和线程B,堆内存和方法区内存共享。但是栈内存独立,一个线程一个栈。
  • 多线程:为了提高程序的处理效率。
  • 对于单核的CPU来说,不能够做到真正的多线程并发,但是可以做到给人一种“多线程并发“的感觉。对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但由于CPU的处理速度极快,多个线程之间频繁切换执行,给人的感觉是多个事情同时在做。

PCB(Process Control Block)进程控制块:描述控制进程的运行,系统中存放进程的管理和控制信息和数据结构。 

PCB一般包括: 

  • 进程ID(PID、进程句柄):它是唯一的,一个进程都必须对应一个PID。
  • 特征信息:一般分系统进程、用户进程、或者内核进程等。
  • 进程状态:运行、就绪、阻塞、表示进程现的运行情况。
  • 优先级:表示获得CPU控制权的优先级大小。
  • 通信信息:进程之间的通信关系的反映,由于操作系统会提供通信信道。
  • 线程保护区:保护阻塞的进程用
  • 资源需求、分配控制信息
  • 进程实体信息:指明程序路径和名称,进程数据在物理内存还是在交换分区中
  • 其他信息:工作单位、工作区、文件信息等。

同一个进程里的若干个PCB pid相同。不同进程的pid是不同的 

PCB不是”简称“是一个数据结构,体现的是 进程/线程是如何实现的,如何被描述的。

        PCB对应的是线程

        一个线程对应多个PCB        

        如果一个进程只有一个线程,就是一个进程对应一个PCB了。

线程安全问题:罪魁祸首——抢占式执行,随机调度。

本质上还是系统里的线程的封装,每个Thread的对象就对应到系统中的一个线程,也就是PCB

start 和 run 区别:

  • start是真正创建了一个线程(从系统这里创建的)
  • run 知识描述了线程要干的活是啥,如果直接在main中调用run,此时没有创建新线程,全是main线程一个人干的活。

进程和线程:

进程包含线程,要想看到线程,要先找到对应的进程,再看进程里有哪些线程。

实现线程方法

1、继承Thread,重写 run 

进程/线程/PCB_第1张图片

接口比抽象类更进一步,抽象类接口则不行,要求方法都是抽象方法。

2、实现Runnable接口 实现一个interface

解耦合,目的就是为了让线程和线程要干的活 之间分离开。

未来改代码,不用多线程,或者线程池,或者协程……此时代码改动较小。

3、使用匿名类,继承Thread

        创建了一个Thread的子类。(子类没有名字)所以才叫做匿名。

        创建了子类的实例,并且让 t 引用执行实例

4、使用匿名内部类,实现Runnable

        这个写法和2本质相同,只不过把实现Runnable任务交给匿名内部类的语法。

        此处是创建了一个类,实现了Runnable,同时创建了类的实例,并且传给Thread的构造方法。

5、使用Lambda表达式(最简单,推荐写法)

        把任务Lambda表达式来描述

        直接把Lambda传给Thread构造方法

        (匿名内部类被重写方法的形参列表)-> {

                        被重写方法的方法体代码

          }

        lambda 表达式只能简化函数式接口匿名内部类的写法形式,且接口中有且仅有一个抽象方法

        上述方法,只是语法规则不同,本质上都是一样的方式,这些方式创建处理啊的线程都是一样的。

抽象类与普通类的区别

  • 抽象类不能实例化,不能new
  • 必须要搞个子类,来继承抽象类
  • 抽象类里还有抽象方法,抽象方法没有方法体,需让子类重写 

你可能感兴趣的:(学习)