【JavaEE】——线程的诞生(超详细、易理解)

简介: 进程对内存的管理,进程间的通信,进程的缺点,线程的概念和特点,进程和线程在内存中的分配方式,进程和线程的结合,进程和线程之间的关系,线程的缺点,有无线程的对比,线程的总结

 一:进程对内存的管理

1:进程的独立性:

进程是如何管理内存的,核心:每个进程都有一块独立的内存,进程与进程之间的内存互不干扰,通常情况下,进程A的内存不能访问进程B的内存

好处“进程独立性”:如果进程A的内存超出了给分配的内存大小(即内存越界)或者出现某些bug导致进程A挂掉,不会影响到进程B的运行

二:“进程间的通信”

引入:虽然进程有独立性,但是有一些任务还需要进程与进程之间进行相互配合去完成

1:内存中的公共空间

进程与进程之间也可以通信,操作系统会在内存当中开辟一块特殊的公共空间,用来进程与进程之间进行“数据交换”,这与进程的“独立性”并不冲突。

2:网络通信

操作系统中提供的“进程间的通信”并不限于上述,在Java中,我们通常以文件和网络的形式来达到“进程间的通信”。后端也大同小异,一般是一组服务器之间进行通信

网络通信(简述)同一台计算机中的不同进程可以通过网络来进行通信,不同计算机的不同进程也可以达到通信的目的(泛用性更广)

三:进程的缺点

引入:对进程的管理和调度(对进程的调度)

前面我们已经学过,像单任务操作系统,并不需要考虑进程这个概念,即不需要对进程进行管理和调度。但是现在的操作系统一般都是多任务操作系统,在一些特殊的场景下,比如任务超多的时候,我们需要频繁地创建和销毁进程时,进程就暴露出它的缺点了

1:背景

在早期web开发的时候,PHP为前端霸主,当时的开发语言是C,开发服务器是基于一种叫(CGI)的技术来实现的,这种技术的模式是,多进程的编程模式

服务器会在同一时刻收到许多请求,服务器基于每一个请求都会申请创建一个进程,然后为请求提供服务,服务完毕后返回响应,销毁进程释放资源。

这个过程中包含着大量频繁的进程的创建和销毁,但是进程的创建和销毁并不容易

2:索取内存资源

进程在创建之前,第一个要索取的资源就是内存。

过程:所以首先就需要向系统申请一块指定大小的内存资源,系统知道后就把所有空闲的内存块通过数据结构组织在一起,然后再在里面查找一个大小合适的内存,最后分配给进程,进程再把依赖的代码和数据通过硬盘加载到内存当中

四:线程

引入:

通过以上线程缺点的描述,我们针对“频繁创建和释放线程需要消耗大量的资源”这一问题,提出了“线程”这一概念来解决。

1:线程的概念和特点

线程也叫“轻量化进程”,线程在进程的基础上,保留了原有的独立调度执行的特点,这种“并发支持”,解决了“申请资源”和“释放资源”带来的额外开销这一问题。

image.gif 编辑 image.gif 编辑

回顾内存指针:在pcb中有一个属性叫内存指针,它可以指向一块内存空间,(即为pcb确定内存空间位置)

回顾进程的独立性:进程与进程间申请的内存空间是彼此独立的,内存空间互不干涉

2:进程在内存中的分配方式

在一个进程当中可以包含多个进程(即图中用一个大进程包含两个小进程来形象描述,可以理解成“进程组”),每个进程都是由pcb来描述的。对于每一个进程来说,它们分配的内存空间是独立的,互不干涉(即pcb的内存指针与内存空间都是一一对应的)

3:线程在内存中的分配方式

对于线程来说就不一样了,可以有多个线程的pcb指向同一块内存空间,重点来了!!!

这就意味着,第一个线程申请了内存空间后,后面的线程就不必在申请了,同样的第一个线程释放资源后,这块内存空间也不必回收,可以留着后面再复用(即多个线程共用一份资源)

同样线程中的pcb也有进程pcb的这些概念(状态,优先级,上下文,记账信息)

4:进程和线程的结合

image.gif 编辑

5:进程和线程之间的关系

每个进程都可以包含一/多个线程,像有三个小线程的小pcb都指向了a,它们获取a中的代码指令的用途不一定相同(即各取所需)有一个线程申请了a这一块空间后,后面的线程就不必在申请了,大大降低了频繁申请空间和释放空间带来的资源浪费

6:线程的缺点

(1)设置线程是有限的

对于上述现成的了解,引入线程不仅可以大大提高进程运行的效率,也可以降低资源浪费,但是引入的线程是越多越好吗?不,有两个问题需要我们注意

①线程数量问题

看图四,有三个pcb的红色箭头(内存指针)指向内存a,共用内存a上的代码指令,那么如果增加箭头数呢(即有10个,100个pcb的内存指针指向a)此时线程与线程之间就会争夺cpu的内存空间,非但不会提高效率,反而会大大增加线程调度所耗费的资源。

②线程间优先级问题

看图四,有三个pcb的红色箭头(内存指针)指向内存a,共用内存a上的代码指令,那么涉及到一个问题,究竟“谁先用,谁后用”,线程和线程之间谈不拢就打一架呗,就可能会导致代码出现一些bug和逻辑上的错误(这就涉及到了线程的安全问题)!!

③线程异常问题

还是看图四:在②的基础上,A线程和B线程谈不拢打了一架,A线程打赢了,说:a内存上代码指令老子就先用了。B不服气,王德发!不让我用,那大家都别用了!!!于是B抛出异常,导致整个大进程都被终止了

7:前后对比

在有线程之前

进程所扮演的角色:既是资源分配的基本单位,也是执行调度的基本单位

在有线程之后

进程专注于资源分配(超大进程去申请B这一块空间)如4的图

线程专注于调度执行(线程去调度内存中的数据、代码)如4的图

8:总结

①两个基本单位

进程包含线程,进程是“资源分配”的基本单位,线程是“执行调度”的基本单位

②资源共享

每一个进程都有自己独立的资源(内存空间和文件描述符表),进程所包含的线程可以共享这一份资源

③独立执行

每一个线程都是一段独立的执行流,可以独立的被cpu进行调度(状态,上下文,文件描述符表,优先,记账信息,线程都有自己独立的一份)

④数量限制

线程不是越多越好,如果线程太多,执行调度的开销就会很大(船上装不下这么多人)

⑤线程安全

同一个进程中的线程可能会相互干扰(抢夺资源),引起线程安全问题(一条船上抢东西吃)

⑥线程异常

同一个进程中的线程如果抛出异常,会影响到其它线程,可能会把整个进程中的所有线程都异常终止(一条船上的人,要死一起死)


相关文章
|
21天前
|
Java
【JavaEE】——多线程常用类
Callable的call方法,FutureTask类,ReentrantLock可重入锁和对比,Semaphore信号量(PV操作)CountDownLatch锁存器,
|
21天前
|
Java 关系型数据库 MySQL
【JavaEE“多线程进阶”】——各种“锁”大总结
乐/悲观锁,轻/重量级锁,自旋锁,挂起等待锁,普通互斥锁,读写锁,公不公平锁,可不可重入锁,synchronized加锁三阶段过程,锁消除,锁粗化
|
21天前
|
Java Go 调度
【JavaEE】——线程池大总结
线程数量问题解决方式,代码实现线程池,ThreadPoolExecutor(核心构造方法),参数的解释(面试:拒绝策略),Executors,工厂模式,工厂类
|
21天前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
21天前
|
Java 调度
|
21天前
|
Java 调度
【JavaEE】——线程的安全问题和解决方式
【JavaEE】——线程的安全问题和解决方式。为什么多线程运行会有安全问题,解决线程安全问题的思路,synchronized关键字的运用,加锁机制,“锁竞争”,几个变式
|
21天前
|
Java API 调度
【JavaEE】——多线程(join阻塞,计算,引用,状态)
【JavaEE】——多线程,join,sleep引起的线程阻塞,多线程提升计算效率,如何获取线程的引用和状态
|
21天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
21天前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
8月前
|
消息中间件 监控 安全
【JAVAEE学习】探究Java中多线程的使用和重点及考点
【JAVAEE学习】探究Java中多线程的使用和重点及考点