并发1️⃣相关概念、线程状态
前言
并发编程涉及知识点
- 进程与线程
- 并发与并行
- 同步与异步
- Java 并发工具、并发问题及解决方案
基础知识
- 接触过 Java Web、JDBC 开发、Web 服务器(最好有分布式框架基础)
- 基于 JDK 8,了解函数式编程、lambda 表达式
- JVM
- 日志,方便输出调试
相关日志配置:基于 log4j
-
log4j.properties
log4j.rootLogger=DEBUG,console #控制台输出的相关设置 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.Threshold=DEBUG log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss:SSS} [%t] - %m%n
-
工具类:debug() 用于输出调试信息。
public class LogUtils { private static final Logger LOGGER = Logger.getLogger(LogUtils.class); public static void debug(Object msg) { LOGGER.debug(msg); } }
1、初识并发编程
1.1、程序、进程、线程
1.1.1、相关概念
程序(procedure)
- 程序由指令和数据组成,是静态的。
- 指令加载到 CPU 才能执行,数据加载到内存才能读写。
- 指令执行过程中需要用到磁盘、网络等设备。
进程(progress)
- 进程可视为程序的一个实例,是动态的(可理解为运行中的程序)。
- 进程用于加载指令、管理内存和 I/O。
- 当一个指令被执行时,程序从磁盘加载到内存,此时开启了一个进程。
- 程序可运行一个或多个实例进程(如 QQ音乐、记事本)。
线程(thread)
- 线程相当于指令流。
- 线程将指令以一定的顺序交给 CPU 执行。
1.1.2、进程 vs 线程
Java 中,进程是资源分配的最小单位,线程是最小调度单位。
- 进程基本上相互独立,线程存在于进程内(一个进程由多个线程组成)
- 进程拥有共享的资源(如内存空间),供其内部的线程共享。
- Windows 中,进程作为线程的容器,自身是不活动的。
通信
- 进程间通信(复杂)
- 同一台计算机:IPC(Inter-process communication)
- 不同计算机:通过网络并遵守共同的协议,例如 HTTP
- 线程通信(简单):线程共享进程的内存(例:多个线程可以访问同一个共享变量)
上下文切换(context switch)
- 含义:内核在 CPU 上对进程(线程)进行切换,即任务切换。
- 一般情况下,线程上下文切换成本比进程低。
1.2、并发、并行
-
串行(serial):同一时间只能做一件事情(单核 CPU)
-
并行(parallel):同一时间可以做多件事情(多核 CPU)
concurrent
单个 CPU 轮流执行线程(线程轮流使用 CPU)
- 单核 CPU 下,操作系统的任务调度器,将 CPU 时间片分给不同程序使用。
- CPU 在线程间的切换非常快,让人感觉是同时运行的(Windows 时间片最小约 15ms)。
- 结论:宏观并发,微观串行。
parallel
多个 CPU 同时执行多个线程。
- 多核 CPU 下,每个 CPU 都可以调度运行线程,线程可以并行执行。
- 通常线程数会远大于 CPU 核数,因此并行和并发是同时存在的。
- 结论:宏观并行,微观存在串行。
1.3、同步、异步
同步和异步,是基于程序调用方的角度
- 同步(synchronization):需要等待结果返回才能继续运行。
- 异步(asynchronization):不需要等待结果返回,就能继续运行。
多线程可以使方法异步执行
- 开启一个线程用于处理比较耗时的操作,避免阻塞主线程。
- 应用举例:Tomcat 中的 异步 Servlet、UI 编程中的异步。
2、线程状态
两种说法
- 操作系统层面:5 种状态
- Java 层面:6 种状态
2.1、OS:五种状态
从操作系统的层面
-
初始:创建线程对象实例(属于语言层面),未与操作系统线程关联。
-
可运行(就绪):线程已与操作系统相关联,等待 CPU 时间片即可运行。
-
运行:线程获取了 CPU 时间片,正在运行。
-
阻塞:线程因某种原因而暂停运行(CPU 不会为阻塞线程分配时间片)。
-
终止:线程执行完毕,生命周期结束(死亡)。
2.2、Java:六种状态(!)
从 Java API 层面来描述
Java Thread 中定义了 State 内部枚举类,包括 6 个线程状态。
-
NEW
:线程对象实例化,但未start()
。 -
RUNNABLE
:调用了start()
。- 线程正在 JVM 中执行。
RUNNABLE
涵盖了 OS 层面的运行、可运行、阻塞
(指 BIO 导致的阻塞)
-
阻塞状态细分
BLOCKED
:等待 Monitor 锁(之后会详解)WAITING
:无限期等待另一个线程执行完某个特定操作。TIMED_WAITING
:在指定等待时间内,等待另一个线程执行完某个特定操作。
-
TERMINATED
:线程代码执行结束(退出)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏