Java深入理解并发、线程、与等待通知机制(一)

并发编程概述

  • 并发编程的重要性

    • 大厂招聘要求掌握多线程编程能力。
    • 并发编程是升职加薪的重要技能之一。
    • 并发提升响应速度、实现异步化、充分利用CPU资源。
  • 单核与多核处理

    • 即使在单核处理器上,也可通过并发实现多个任务交替执行。
    • 多核处理器下,并发能真正实现并行执行。
  • QQ/微信并发示例

    • 输入文字、发送消息、接收信息三者同时发生,体现并发特性。
    • 若使用单线程,则需串行完成以上操作,用户体验差。

进程与线程概念解析

  • 进程定义

    • 进程是一个程序的实例,包含指令、内存管理、I/O操作等。
    • 类比面向对象中类与对象的关系,程序是类,进程是对象。
    • 进程是操作系统中资源分配的最小单位。
  • 线程定义

    • 线程是操作系统中CPU调度的最小单位。
    • 一个进程中可以包含多个线程,但线程必须依附于进程存在。
    • Linux早期无独立线程概念,后称为轻量级进程(LWP)。
  • Java中的线程机制

    • JVM本身作为一个进程,内部自动启动多个线程,如主线程、Finalizer线程、Reference Handler线程等。
    • 即使是最简单的Java程序,也会默认启动多个线程。

进程间通信方式

  • 常见IPC机制
    • 管道(Pipe):分为匿名管道(父子进程通信)与命名管道(任意两个进程通信)。
    • 信号(Signal):用于向应用程序发送特定事件通知。
    • 消息队列(Message Queue):类似MQ,用于进程间传递消息。
    • 共享内存(Shared Memory):多个进程访问同一块内存区域,效率高但需同步控制。
    • 信号量(Semaphore):用于控制对共享资源的访问。
    • 套接字(Socket):支持跨机器通信,也可用于本地进程通信(Unix Domain Socket)。

CPU核心与线程关系

  • 物理核心与逻辑处理器

    • 物理核心数决定实际并行能力。
    • 逻辑处理器来自超线程技术,允许一个物理核心模拟多个逻辑核心。
  • Runtime类获取核心数

    • Runtime.getRuntime().availableProcessors() 返回的是逻辑处理器数量。
    • 不同架构平台(Intel vs AMD/ARM)返回结果可能不同。

上下文切换原理

  • 上下文切换定义

    • 操作系统保存当前线程状态并加载另一个线程状态的过程。
    • 包括寄存器、程序计数器、缓存数据等。
  • 上下文切换代价

    • 一次上下文切换通常需要约5,000~20,000个时钟周期。
    • 相较之下,普通指令执行只需几个到几十个时钟周期。
  • 性能调优建议

    • 上下文切换频繁会导致性能下降。
    • 使用工具如vmstat、pidstat监控切换频率。

并发与并行区别

  • 并行(Parallelism)

    • 同一时刻执行多个任务。
    • 依赖多核CPU,如两个队伍同时使用两台售货机。
  • 并发(Concurrency)

    • 一段时间内交替执行多个任务。
    • 如一个售货机被两个队伍轮流使用。
    • 体现为时间片轮转下的"看似同时"。

Java线程创建方式

  • 继承Thread类

    • 创建子类并重写run()方法。
    • 实例化后调用start()启动线程。
  • 实现Runnable接口

    • 实现run()方法,传入Thread构造器。
    • 更推荐使用,避免类继承限制。
  • Callable + FutureTask

    • Callable<V>提供返回值,适用于需要结果的任务。
    • FutureTask包装Callable,作为Runnable传入线程。
    • 通过future.get()获取异步执行结果。

线程终止方式

  • 自然终止

    • run()方法执行完毕。
    • 抛出未捕获异常导致提前结束。
  • 强制终止(不推荐)

    • stop()、suspend()、resume()等方法已废弃。
    • 原因:不会释放资源,易造成死锁、文件损坏等问题。
  • 中断机制(推荐)

    • 调用interrupt()设置中断标志位为true。
    • 线程主动检查isInterrupted()或interrupted()状态。
    • 阻塞方法(如sleep()、get())抛出InterruptedException,可响应中断。

线程启动与运行区别

  • start()方法

    • 启动新线程,在JVM中注册并与操作系统线程绑定。
    • 只能调用一次,否则抛出IllegalThreadStateException。
  • run()方法

    • 普通方法,直接调用仅在当前线程中执行。
    • 可重复调用,不影响线程状态。
    • 示例:调用thread.run()将在主线程中执行
相关推荐
golang学习记13 小时前
IDEA 2026年的玩法已经完全不同
java·ide·intellij-idea
紧跟先前的步伐13 小时前
Go AI Agent 实战 05|Temperature 与生成参数:让模型输出可控
java·人工智能·golang
金銀銅鐵14 小时前
[Java] 展示添加元素时 ArrayList 的内部变化
java·后端·ai编程
斌糖雪梨14 小时前
spring auth 核心流程详解
java·后端·spring
文丑颜不良啊15 小时前
LeetCode201~225题目解析
java·leetcode
SL_staff17 小时前
4G设备掉线三层归因指南:SIM卡、模组、JVS-IOT网关配置精准锁定
java·物联网·产品
Wang's Blog18 小时前
Java 项目实战: 交友项目 - 黑名单:取消黑名单
java·windows·交友
杨杨杨大侠18 小时前
DeepSeek Harness:连 Agent Loop 都能替换的插件架构
java·人工智能·agent
SL_staff18 小时前
私有化低代码运维三重雷区:JVS开源栈中的Kafka/ES/RabbitMQ治理实践
java·低代码·全栈
yuniko-n18 小时前
【算法】约瑟夫环问题
java·算法