线程与进程:高效并发编程的核心奥秘

今天就主要来讲一下进程和线程部分的知识点,希望对于学习JUC的你会有所帮助!

进程与线程的简单介绍

进程
  1. 首先我们先来简单的讲一讲什么是进程?进程我们可以理解为我们电脑上的一个个应用实例,当我们双击打开这个应用的时候,就相当于是启动了一个进程。
  2. 接着是,这个应用程序肯定是有很多的指令和数据 的吧,这些指令如果想要去执行,那么就必须要把指令加载到CPU执行,数据加载到内存; 有的应用程序还需要用到联网和磁盘,因此指令在运行的过程中还需要用到网络,磁盘等设备【这个部分如果往下深入就是到了操作系统部分了,在此处暂时不考虑往下进行延申,后续会开操作系统的专栏】
  3. 综上,进程就是用来加载执行指令,管理内存,管理IO【磁盘的写入和读出】
线程
  1. 一个进程在运行的过程中,是需要完成一系列的任务的,那么我们是不是可以考虑将大任务去分解成一个个小任务,让手底下的小线程去完成这一个个子任务即可
  2. 所以一个进程之内可以分为多个线程
  3. 一个线程就是一个指令流,将指令流中的一条条指令交给CPU去执行,让线程去完成这一个个的小任务
  4. java中,线程作为最小的调度单位,进程作为资源分配的最小单位;在windows中进程是不活动的,只是作为线程的容器
二者对比
  1. 进程之间是相互独立的,而线程是存在于进程内部的;类比:进程是一个大的车间,线程是里面的一个个小员工,每个员工负责一个子任务,共同来完成车间的大任务
  2. 进程拥有共享的资源:在这个进程内的线程之间的资源都是共享的,比如内存空间和资源;类比车间里面的 补给品和空调/风扇,都是这个车间内的工作人员所共享的!
  3. 进程间的通信是比较复杂的;同一台计算机进程之间的通信为IPC;不同机器之间的进程通信需要通过网络,并遵守共同的协议,比如HTTP,TCP等协议【涉及到计算机网络的知识点了,后续深入的话,也会开一个专栏来讲这个部分的知识点】
  4. 线程间的通信:注意这个也是要分情况的!如果是不同进程内的线程进行通信的话,代价还是比较大的【毕竟都不是一个车间内的人,还需要去到别的车间和其他人进行交流,还需要经过一系列的安检和检查,还是比较麻烦的】
  5. 如果线程间的通信是在同一个进程下的话,就相对比较简单了,因为同一个进程下的线程是共享内存空间的
  6. 线程的上下文切换更加的轻量,线程的上下文切换的代价比进程的上下文切换要小
补充

什么是上下文切换?

  1. 这里先简单的讲一下,就是在CPU内部是通过时间片轮转的方式来分配的
  2. 比如线程1占用了时间片1,在这个时间片内去执行任务;
  3. 但是经过了这个时间段之后,线程1的任务还没有执行完,这个时候操作系统就告诉线程1,你的时间用完了,该换到其他的线程来执行任务了
  4. 那么这个时候线程1是不是要记录一下当前线程的执行情况,当前任务进行到了一个什么样的程度,保存下来【像我们读书的时候,如果突然有事,是不是要记下一个书签,有空了直接从这个书签位置记录处开始读】,然后准备切换到下一个线程
  5. 线程2这个时候来了,是不是需要加载当前线程的一些执行任务所需要的资源,保存线程1的数据,开始执行线程2的任务

这个部分呢还是有点小复杂的,后续在讲操作系统的时候会深入的去聊一下这个部分,在这里可以简单的理解一下就好:上下文切换,就是切换执行任务的过程

并行与并发

并行:就是物理上的多个任务来同时进行执行的过程!

并发:在单核CPU上,通过时间片轮转的方式来轮流执行一个个的小任务;但是为什么我们觉得即使在单核CPU的电脑上,我一遍写文章,一遍听歌,看起来是并行的,但实则在单核CPU内部,是通过时间片轮转的方式来轮流执行的,为什么我们感知不到呢?因为每一个时间片的时间都是非常短的,因此在切换的时候,一般是感知不到的

单核CPU的情况下:

多核CPU的情况下:

在多核CPU的情况下,只要线程数量比CPU内核的数量要多的话,那么CPU就是并行+并发一块执行的【因为难免会在线程之间进行来回的切换操作】

应用

应用之异步调用

思考:

  1. 如果在业务开发的代码当中需要进行IO操作的话,可以考虑使用多线程工具来进行优化,比如我新开一个线程来专门地去处理这个调度任务,不需要CPU进行等待操作
  2. 那么我是不是可以类比,凡是占用CPU时间比较长的工作,我能不能都开启一个新的线程,去专门执行这个任务,然后主线程留着去执行重要的业务代码和逻辑
  3. 异步编程主要是用在对于结果要求本身不是很严格的环境当中去进行的【并不要求我必须先算出结果才能往下继续运行!】
黑马点评下单回顾

像我们前面学习过的黑马点评项目,在下单的时候就是用到了这个技术,回顾一下当时的场景

  1. 如果一个时间段内,一下子有上千万的请求打过来,我们数据库肯定是扛不住的,因此我们可以考虑引入redis来进行一个缓冲,来降低数据库的压力
  2. 但是用户的整个下单流程是非常长的,在整个系统中的业务线非常的长,我们是不是可以考虑一下对这个业务线进行适当的裁剪;于是我们对用户实际下单,扣减库存,通知发货的部分可以进行一个异步操作处理
  3. 这个时候就可以引入 消息队列 来帮助我们起到一个削峰填谷的作用,按照数据库可以接受的方式来写入数据,不至于一下子把数据库打宕机;
  4. 整个的思想就是一个异步操作!后续会开一个专栏专门来讲一下有关于消息队列的知识点!

在这里展示的是异步操作:

异步进行执行的话【这里是开了一个新线程】,可以观察到在此处两个线程是同一时刻开始并行执行的!

应用之提高效率

举个例子:

  1. 在这里如果是多核CPU的话,开启多个线程来执行任务会相对的更快一些
  2. 如果是单核CPU的话,如果同样是开启了多核来进行对应的任务,执行任务的速度反而是会下降,因为在单核CPU当中,如果开启了多个线程,是需要进行线程之间的上下文切换,导致浪费了大量的时间【图片】
相关推荐
Lucis__4 小时前
Linux系统收官篇:线程学习的一些心得总结
linux·学习·线程
ShineWinsu5 小时前
对于Linux:环境变量的解析
linux·面试·笔试·进程·环境变量·本地变量·getenv
ShineWinsu3 天前
对于Linux:进程地址空间(虚拟地址空间)的解析
linux·服务器·面试·笔试·内存·进程·虚拟空间
艾莉丝努力练剑4 天前
【Linux线程】Linux系统多线程(一):线程概念
java·linux·运维·服务器·开发语言·学习·线程
ShineWinsu6 天前
对于Linux:进程优先级、进程切换以及进程调度的解析
linux·面试·笔试·进程·进程切换·进程调度·进程优先级
czhc11400756637 天前
winform 330 跨线程 异步
wpf·线程·winform
艾莉丝努力练剑7 天前
【Linux信号】Linux进程信号
linux·运维·服务器·学习·操作系统·进程·信号
DJ斯特拉8 天前
JUC基础
java·jvm·juc
庞轩px10 天前
AQS(AbstractQueuedSynchronizer)源码深度解析:从CLH队列到ReentrantLock实现
java·并发编程·juc·aqs·reentrantlock