conanan's blog conanan's blog
首页
关于
  • 分类
  • 标签
  • 归档
  • Java
  • Java Web
  • 工具

    • Maven
  • MySQL
  • Redis
  • Git
  • Vim
  • Nginx
  • Docker
GitHub

Evan Xu

前端界的小学生
首页
关于
  • 分类
  • 标签
  • 归档
  • Java
  • Java Web
  • 工具

    • Maven
  • MySQL
  • Redis
  • Git
  • Vim
  • Nginx
  • Docker
GitHub
  • 基础

  • API

  • Container

  • 多线程

    • 基本概念
      • 思维导图
      • 操作系统、程序、进程、线程
        • 操作系统(OS)
        • 程序(Program)
        • 进程(Process)🔥
        • 线程(Thread)🔥
        • 【面试】进程和线程的关系和区别?🔥
        • 【实例】一个 Java 应用程序至少有三个线程 🔥
        • 【实例】房子
      • 多线程
        • 概念
        • 为什么需要多线程、优点 🔥
        • 多线程的使用场景 🔥
        • 多线程局限 🔥
      • 串行、并发、并行
        • 异同 🔥
        • 单核、多核 CPU
        • 是什么让并发和并行称为可能?🔥
      • 高并发
        • 什么是高并发?
        • 高并发和多线程的联系和不同?🔥
        • 高并发的指标
      • 同步异步、阻塞非阻塞
        • 同步、异步 🔥
        • 阻塞、非阻塞 🔥
        • 组合示例 🔥
    • 基本使用
    • 线程生命周期
    • 共享模型—管程(悲观锁,阻塞)
    • Monitor & synchronized 原理
    • 应用
    • 设计模式
    • 8 IO
    • 9 NIO
    • 10 AIO
    • 11 Network
    • 2 Object Orientation-4 注解
    • 12 Reflect
  • 16 9,10,11新特性
  • 17 Test
  • 18 设计原则&设计模式
  • JDBC
  • Java
  • 多线程
conanan
2020-12-14

基本概念

# 多线程—基本概念

# 思维导图

# 操作系统、程序、进程、线程

# 操作系统(OS)

操作系统(OS)是包含多个进程的容器,而每个进程又都是容纳多个线程的容器

# 程序(Program)

程序是为完成特定任务、用某种程序设计语言编写的一组指令的集合。即指一段静态的代码,静态对象。

# 进程(Process)🔥

程序要运行,就必须将其加载到 CPU(如缓存器中),然后操作内存中的数据、磁盘中的数据、网络设置等。

进程是正在运行的程序。是程序的一次执行过程,是系统进行资源分配的基本单位。是动态对象。

  • 每个进程都有一个独立的内存空间,一个应用程序多次运行对应多个进程。
  • 它是一个动态的过程,系统运行一个程序即是一个进程从创建、运行到消亡的过程,即生命周期。

Oracle 文档中定义进程是:使用 fork(2)系统调用创建的 UNIX 环境(例如文件描述符,用户 ID 等),它被设置为运行程序

可以使用活动监视器查看,有进程、线程数量等

image-20210206215726196

大部分程序可以同时运行多个实例进程(如浏览器),也有的程序只能同时运行一个实例进程(如网易云音乐)

# 线程(Thread)🔥

线程是进程中的一个执行单元/路径,负责当前进程中程序的执行,是处理机调度的基本单位

Oracle 文档中定义线程是:在进程上下文中执行的一系列指令

  • 每个线程拥有独立的运行栈和程序计数器

  • 一个进程中的多个线程共享相同的内存单元/内存地址空间:它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能会带来安全隐患

  • 线程切换的开销小

  • 线程一对一映射到 OS 的内核线程,使用 JNI 实现的。若是支持协程的语言,可能几十个协程对应一个 OS 线程

    image-20210208002102861

# 【面试】进程和线程的关系和区别?🔥

# 【实例】一个 Java 应用程序至少有三个线程 🔥

一个 Java 应用程序,至少有三个线程?:main()主线程,gc()垃圾回收线程,异常处理线程。当然如果发生异常,会影响主线程。查看 debugger 模式时可以看到如下代码的线程

public class Test {
    public static void main(String[] args) {
        System.out.println();
    }
}
1
2
3
4
5

image-20210207224614131

  • main:主线程,程序的入口
  • Finalizer:负责对象的 finalize() 方法,垃圾回收,不推荐主动使用
  • Reference Handler:和 GC、引用相关的线程
  • Signal Dispatcher:信号调度,把操作系统发来的信号分发给适当的处理程序

# 【实例】房子

  • 客厅:每个线程随时进出
  • 厨房:线程并发,线程间通信
  • 卫生间:需有锁
  • 卧室:线程独立资源,如堆栈

# 多线程

# 概念

若一个进程同一时间并行执行多个线程,就是支持多线程的。一个进程中至少有一个线程

# 为什么需要多线程、优点 🔥

若是单核 CPU,只使用单个线程先后完成多个任务(调用多个方法),肯定比用多个线程来完成用的时间更短(线程切换时间长),但是目前大部分都是多核 CPU,那多线程究竟有什么好处呢?为什么要使用多线程?

  • 最主要的目的就是提高 CPU 利用率

    • 提高处理速度
    • 避免无效等待(IO 时可以做其他事)
    • 提高用户体验,应用程序响应快,避免卡顿,缩短等待时间
      • 并行处理,提高性能,通常是服务器领域(例如 Tomcat),用多个线程去接收进来的 HTTP 请求,而不是排队等待单一的线程处理
      • 在 Android 开发中,主线程的重要任务之一是绘制屏幕界面,即 UI 线程,该线程中不允许进行 IO 操作或网络请求,目的就是避免卡顿,影响用户的交互
  • 便于编程建模,改善程序结构

    把这个大的任务 A 分解成几个小任务,任务 B、任务 C、任务 D,分别建立程序模型,并通过多线程分别运行这几个任务,便于理解和修改

  • 计算机性能定律:摩尔定律失效,阿姆达尔定律登上舞台

    • 摩尔定律:当价格不变时,集成电路上可容纳的元器件的数目,约每隔 18-24 个月便会增加一倍,性能也将提升一倍。
    • 阿姆达尔定律:
      • 结论:一般情况下,处理器越多,程序执行的速度就会越快,但是会有一个上限,上限取决于程序中串行部分的比例,并行的比例越高,多处理器的效果越明显。但是大部分程序都是串行占比多!

image-20210207231426774

# 多线程的使用场景 🔥

  • 为了同时做多件不同的事:开网页同时听歌;后台定时任务

  • 为了提高工作效率、处理能力:Tomcat;并行下载;NIO

    程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等

  • 需要同时有很大并发量的时候:压测

# 多线程局限 🔥

  • 性能问题:上下文切换的消耗
  • 带来线程安全问题:
    • 数据安全问题:i++总数不一致
    • 线程活跃性问题:线程饥饿、死锁、活锁
  • 异构化任务(任务结构不一样)很难高效并行。即对于串行任务无法改造为多线程

# 串行、并发、并行

# 异同 🔥

  • 串行:按顺序执行
  • 并发:指两个或多个线程在同一个时间段内发生,逻辑上同时发生,单核即可实现。左图
  • 并行:指两个或多个线程在同一时刻发生(同时发生),物理上同时发生,多核可以实现。并行一定是并发,反之不是。右图

image-20210207232912767

# 单核、多核 CPU

  • 单核 CPU,其实是一种假的多线程,操作系统中的任务调度器,将 CPU 的时间片(Win 下最小时间片为 15ms)分给不同的线程使用,一个时间片内只能执行一个线程的任务,即线程还是串行执行的,但是因为时间片特别短,因此感觉不出来。总结一句话就是:微观串行,宏观并发。

    任务调度器具体如何分配时间片,有分时调度模型(时间片轮转,平分时间片)、抢占式调度模型(优先级高则时间片多)

    例如:虽然有多车道,但是收费站只有一个工作人员在收费,只有收了费才能通过,那么 CPU 就好比收费人员。如果有某个人不想交钱,那么收费人员可以 把他“挂起”(晾着他,等他想通了,准备好了钱,再去收费)。

  • 多核 CPU,在单核基础上可以并行执行多个线程,能更好的发挥多线程的效率。现在的服务器都是多核的。

# 是什么让并发和并行称为可能?🔥

  • 操作系统升级,抢占式任务处理,时间片轮转;
  • 单核 CPU 升级,频率越来越高,速度越来越开,让并发称为可能
  • 多核 CPU 升级,让并行称为可能;
  • 编程语言升级,支持并发

# 高并发

# 什么是高并发?

服务器短时间可以处理非常多个请求,如双十一、过年微信摇一摇红包

# 高并发和多线程的联系和不同?🔥

  • 多线程是高并发其中一种重要的解决方案,高并发是一种服务器状态
  • 高并发并不意味着是多线程,如 Redis

# 高并发的指标

  • QPS(Queries Per Second):每秒查询数

  • TPS:每秒处理事务数

  • 带宽

  • PV(Page View):一天访问量。。。

  • UV(Unique Visitor):一天访问量去重

  • IP:不同 IP 访问量

  • 并发连接数(The number of concurrent connections)

  • 服务器平均请求等待时间 TPR(Time per request):across all concurrent request

# 同步异步、阻塞非阻塞

参考知乎

# 同步、异步 🔥

  • 被调用者是否主动告诉调用者结果,不主动则应用层还是在向系统内核轮训

  • 以调用方角度来讲,如果

    • 需要等待结果返回,才能继续运行就是同步
    • 不需要等待结果返回,就能继续运行就是异步

    即前序结果对后续有影响时使用同步;没有影响时使用异步即可(如 IO、网络请求等)

鸣笛烧水壶就是异步的示例

image-20210207235724348

image-20210207235751625

# 阻塞、非阻塞 🔥

调用者(线程发出请求,如 HTTP)是否阻塞等待

# 组合示例 🔥

  • 同步阻塞:开始烧水后,我们一直盯着水壶
  • 同步非阻塞:开始烧水后,我们每隔三五分钟过来看一下水壶
  • 异步阻塞:带有鸣笛的水壶开始烧水后,我们一直盯着水壶。常用于结果影响后续进程
  • 异步非阻塞:带有鸣笛的水壶开始烧水后,我们干其他事去了,鸣笛后再过来
编辑
上次更新: 2021/07/07, 14:41:01
6 Container-习题
基本使用

← 6 Container-习题 基本使用→

最近更新
01
线程生命周期
07-06
02
线程安全理论
06-24
03
并发简史
06-24
更多文章>
Theme by Vdoing | Copyright © 2019-2021 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×