本章主要是介绍线程、进程和线程的基本创建。
1.线程和进程
1.1 进程
在操作系统中,进程是资源分配的基本单位。我们可以将进程理解为是计算机运行起来的一个程序或者是任务。
1.1.1 进程管理
进程是由操作系统进行管理的,一般是通过 " 描述 " + " 组织 "。操作系统会通过一个结构体变量PCB(进程控制块),来描述出一个进程的各种属性,并通过使用一定的数据结构将若干个PCB连接起来。
1.1.2 PCB的核心属性
//PCB是什么?
PCB(Process Control Block)是操作系统为每个进程创建的唯一数据结构,用于记录进程的全部管理和控制信息。它是进程存在的唯一标识,进程被创建时生成PCB,终止时销毁PCB。
PCB的三大核心属性:PID(进程的标识符)、内存指针、文件描述符表。
1.1.3 进程的调度
CPU通过并发的方式完成进程的调度,核心在于时间片轮转和状态切换。
1)时间片分配
CPU将执行时间划分为若干个小的时间片,每个进程分配一个时间片,当时间片耗尽,无论进程是否完成,CPU都会强制切换至下一个进程。
2)就绪队列管理
所有就绪进程按照调度算法排入队列。调度器从队头选取进程分配时间片,时间结束后的线程移回队尾等待下一次调度。
3)抢占式调度
高优先级进程先执行。
1.2 线程
**1)**线程也叫轻量级进程,线程创建销毁的开销会比进程低很多。
**2)**线程是操作系统调度执行的基本单位。每个线程都是一个执行流,都可以放到CPU上执行;线程调度和进程基本一致,但在同一个进程中线程可共用PCB的内存指针和文件描述符表。
**3)**一个进程包含多个线程
**4)**多线程同时操作一个数据可能会产生冲突,引发 " 线程安全 " 问题。
1.3 线程和进程的区别
**1)**进程是操作系统资源分配的基本单位;线程是操作系统调度执行的基本单位;
**2)**进程之间资源不能共享;同一个进程的线程之间却可以共享资源;
**3)**进程之间不会相互影响;同一个进程中某个线程出现异常,可能会影响其他线程;
**4)**进程之间通常不会有 " 资源冲突 " 的情况;同一个进程的线程之间,经常容易出现资源访问冲突;
我们可以将线程和进程理解为铜丝和导线的关系。一根导线里可以有若干根铜丝,而且导线与导线之间有绝缘层,不会相互影响,而同一根导线的铜丝之间有可能会相互导电。


2.线程创建
2.1 线程创建的步骤:
**1)**创建一个新的类,让这个类去继承标准库的Thread类,在这个类中重写 run 方法;

//重写和重载的区别
重载(Overload):在同一个类中,方法名相同但参数列表不同(参数的类型、数量或者顺序不同)
重写(Override):在继承关系中,子类重新定义父类的方法,要求方法名、参数列表、返回类型完全相同(返回类型可以为父类返回类型的子类)
**2)**在main()方法中先创建一个创建一个 Thread 的实例,再调用 start 方法启动线程;
run方法是不需要被手动调用的,它属于是一个回调函数,当我们调用 start 方法启动线程时,就可以调用操作系统的API在系统内部创建一个线程,当这个线程被创建好了之后,就会自动执行上面重写的 run 方法

//回调函数
在 Java 中,回调函数是一种核心编程模式 ,它允许将一个方法作为参数传递给另一个方法,并在特定事件或条件满足后被调用。其本质是 *"方法作为参数传递 + 控制权反转"*:调用方定义逻辑并传递给被调用方,由被调用方在适当时机主动执行该逻辑。
运行一下,就会有 " hello thread " 生成,但好像单单这样看不出多线程的效果

我们可以通过调整一下run和mian方法观察一下多线程的运行效果


我们在输出的两边同时加上一个循环,一执行就会发现我们的 " hello thread " 和 " hello main " 是交替出现的

我们可以通过下面的流程图看一下原理

mian方法自身对应的线程为主线程,run方法创建的是新的一般线程,两个线程并发进行
**!!!**要注意看到演示效果后记得把程序停止,防止因为循环快速进行而产生比较高的功率而使电脑发热。
2.2 sleep
我们这里也可以通过sleep方法使线程休息一下,sleep是Thread的一个静态方法,直接通过类名调用即可

这里的1000是指休息的毫秒数,1000ms即1s,而这里的波浪线是我们需要处理的一个异常,trt-catch一下就可以了


此时我们运行程序就会发现,这个 " hello thread " 和 " hello main " 确实是隔了一秒才交替出现的

但他们不是绝对的交替出现的,还是有出现两个 " hello thread " 的情况,这反映我们操作系统的调度过程可以近似看成是 " 随机 " 的,我们通过调用sleep方法,使两个线程堵塞,而当1000ms后会先调用哪一个线程,这个是不确定的,具体需要看操作系统的调度。