探索Java并发编程--从基础到高级实践技巧

Thread(线程)

线程 = 程序执行的最小单位(一个进程至少有一个线程)。线程内有自己的执行栈、程序计数器(PC),但与同进程内其他线程共享堆内存与进程资源

在java中,线程由java.lang.Thread表示,但我们通常不直接操作裸线程,而用更高层的并发工具(线程池、任务、并发集合等)

一、线程的生命周期与常见操作

状态:NEW、RUNNABLE、BLOCKED / WAITING / TIMED_WAITING、TERMINATED

  • NEW:对象创建后,未start()
  • RUNNABLE:可运行(包括实际运行或等待运行)
  • BLOCKED:等待获取对象监视器(synchronized)
  • WAITING:等待其他线程通知(Object.wait()、Thread.join()无超时)
  • TERMINATED:run方法返回或抛出异常结束

常用方法:

  • start():启动线程(不要直接调用run,会变成普通方法调用)
  • join():等待线程结束
  • sleep():当前线程休眠(会释放CPU,但不释放锁)
  • interrupt():中断线程(合作式,需要线程内检查isInterrupted()或捕获InterruptedException)
  • yield():礼让(建议少用,平台依赖)

二、创建线程

  1. 继承Thread
// 问题:单继承限制、职责不清(把任务和线程绑定)
class MyThread extends Thread {public void run() { /* 任务 */ }
}
new MyThread().start();
  1. 实现Runnable
// 好处:解耦任务和线程、可复用
Runnable task = () -> { /* 任务 */ };
new Thread(task).start();
  1. 实现Callable + Future(用于返回值 / 异常)
// 支持返回值和抛异常
Callable<Integer> c = () -> 1+2;
Future<Integer> f = executor.submit(c);
Integer result = f.get(); // 阻塞取结果
  1. 使用线程池(ExecutorService / ThreadPoolExecutor)
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(() -> { /* 任务 */ });
pool.shutdown();
// 不要滥用Executor.*生成的未定制池(可能使用无界队列或者不合适的场景)一般直接构造ThreadPoolExecutor并调参
  1. ForkJoinPool(分治、并行流)
  • 适合CPU密集型、可分解任务(RecursiveTask)。采用工作窃取(work-stealing)
  1. CompletableFuture(异步组合)
  • 异步流式编程supplyAsync、链式 thenApply、异常处理 exceptionally,能把异步任务组合成复杂流程。
  1. 虚拟线程(Project Loom —— 概念)
  • 新一代思想:大量“轻量级线程”由 JVM 管理,降低线程/请求的成本,能用同步编程模型写大并发程序。
  • (提示:具体语法/可用性随 JDK 版本变化,写生产代码前确认 JDK 支持情况。)

三、同步与内存可见性

并发核心问题是:共享可变状态会导致竞态、可见性问题

  1. synchronized(内置锁)

    • 监视器(monitor):synchronized修饰方法或代码块
    • 可重入(同一线程可重复获得同一把锁)
    • wait() / notify() / notifyAll()在持锁状态下使用,用于线程间协作
    // 特点:保证同一时刻只有一个线程能执行临界区代码,并且进入 / 退出时会触发内存可见性更新/*单例模式(懒汉式加锁)
    */
    public class Singleton {private static Singleton instance;public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
    }/*多线程安全更新共享资源
    */
    public class Counter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
    }/*保证集合安全(eg:ArrayList在多线程下不安全,可用Collections.synchronizedList包装)
    */
    
  2. volatile

    • 保证可见性(写入一个volatile变量后,后续读能看到最新值)和禁止指令重排序(对单个变量)
    • 不能替代锁来保证复合操作的原子性(比如count++不是原子性)
    // 特点:让一个线程修改的变量能立即被其他线程看到;禁止指令重排序。
    //     适合 状态标志、开关类变量
    /*线程停止标志
    */
    class Task implements Runnable {private volatile boolean running = true;public void run() {while (running) {// do work...}}public void stop() {running = false; // 立刻被其他线程看到}
    }
    /*配置热更新一个后台线程定时刷新配置,把值写入volatile变量,业务线程能马上读到新值
    */// 注意:下面这种情况要用synchronized或AtomicInteger
    
  3. Lock(java.util.concurrent.locks)

    • ReentrantLock:比synchronized更灵活(可中断获取锁、可轮询、可超时),支持Condition(类似多个wait / nottify集合)
    • ReadWriteLock:读写分离锁,读多写少场景有利
    // 显示锁,比synchronized更灵活,可定时、可中断、支持多个条件队列
    /*尝试获取锁(避免死等)
    */
    ReentrantLock lock = new ReentrantLock();
    if (lock.tryLock(1, TimeUnit.SECONDS)) {try {// 临界区} finally {lock.unlock();}
    } else {// 获取锁失败,执行降级逻辑
    }/* 读写分离(适合读多写少)
    */
    ReadWriteLock rwLock = new ReentrantReadWriteLock();
    Lock r = rwLock.readLock();
    Lock w = rwLock.writeLock();
    
  4. 原子类(AtomicInteger / Long / Reference)

    • 基于CAS(无锁算法),用于计数等简单场景。注意ABA问题(可用AtomicStampedReference)
    // 基于CAS实现的无锁并发,常用于计数器、序列号
    /*高性能计数器
    */
    private AtomicInteger count = new AtomicInteger();
    public void increment() {count.incrementAndGet();
    }/*并发限流 / 统计QPS、在线人数统计,避免用synchronized降低性能
    */
    
  5. 内存模型(JMM)要点

    • 主内存 + 工作内存(线程本地缓存),写到主内存后其他线程可见。volatile / 锁会产生内存屏障,保证可见性与有序性

四、常用并发工具(java.util.concurrent)

  • 线程池:ThreadoolExecutor(核心、最大线程数、队列、饱和策略)
  • 阻塞队列:ArrayBlockingQueue,LinkBlockingQueue,PriorityBlockQueue(常用于生产者-消费者)
  • 同步辅助类:CountDownLatch, CyclicBarrier, Semaphore, Phaser, Exchanger
  • 并发集合:ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue
  • ForkJoinPool(并行任务)
  • BlockingQueue + ThreadPool:典型生产者-消费者模式
  • FutureTask:可作为Runnable也可获取结果,常用于把Callable封装成任务

五、线程安全问题与常见陷阱

  • 竞态条件(race condition):并发修改同一状态导致错误结果
  • 死锁(deadlock):两个或多个线程互相持有对方需要的锁。四要素:互斥、持有并等待、不可剥夺、循环等待
  • 活锁(livelock):线程不断执行但无法取得进展(一直让步)
  • 饥饿(starvation):某线程长期无法获得CPU或锁资源
  • 优先级反转(priority inversion):低优先级线程持锁导致高优先级线程等待
  • 内存泄露(ThreadLocal):线程池中使用ThreadLocal若不remove(),会造成对象无法回收(尤其在容器应用中)

排查工具:jstack(线程dump)、jvisualvm、jconsole、应用日志、线程名 / ID打点、Flight Recorder。线程dump是定位死锁 / 阻塞的利器

六、守护线程(Daemon)vs 用户线程(User)

  • 用户线程:只要存在任意用户线程,JVM不会退出
  • 守护线程:JVM在所有用户线程结束后会退出,即使守护线程还在跑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96303.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go语言实战案例-开发一个Markdown转HTML工具

这个小工具可以把 .md 文件转换为 .html 文件&#xff0c;非常适合写笔记、博客或者快速预览 Markdown 内容。&#x1f4cc; 案例目标• 读取一个 Markdown 文件• 使用开源库将 Markdown 转换为 HTML• 将 HTML 输出到新文件中&#x1f4e6; 所需库我们用 goldmark 这个 Markd…

基于51单片机的太阳能锂电池充电路灯

基于51单片机的太阳能锂电池充电路灯系统设计 1 系统功能介绍 本设计以 STC89C52单片机 为核心&#xff0c;构建了一个能够利用太阳能为锂电池充电并智能控制LED路灯的系统。系统结合了 光照检测电路、LED灯电路、按键检测电路、太阳能充电电路 等模块&#xff0c;实现了节能、…

PAT 1178 File Path

这一题的大意是给出了一个windows的文件夹目录&#xff0c;让我们按照所属的目录关系&#xff0c;来找相应的目录是否存在&#xff0c;如果存在&#xff0c;就输出找到该文件的路径&#xff0c;如果不存在输出error 我的思路是用合适的树形结构保存下来目录的所属关系&#xff…

云原生部署_k8s入门

K8S官网文档&#xff1a;&#xfeff;https://kubernetes.io/zh/docs/home/Kubernetes是什么Kubernetes 是用于自动部署、扩缩和管理容器化应用程序的开源系统。 Kubernetes 源自 &#xff0c;Google 15 年生产环境的运维经验同时凝聚了社区的最佳创意和实践。简称K8s.Kubernet…

实战项目-----Python+OpenCV 实现对视频的椒盐噪声注入与实时平滑还原”

实战项目实现以下功能&#xff1a;功能 1&#xff1a;为视频每一帧添加椒盐噪声作用&#xff1a;模拟真实环境中图像传输或采集时可能出现的噪声。实现方式&#xff1a;读取视频的每一帧。随机选择 10000 个像素点&#xff0c;将其设置为黑色&#xff08;0&#xff09;或白色&a…

Day42 PHP(mysql注入、跨库读取)

一、sql注入基本原理&#xff1a;没有对用户输入的数据进行限制&#xff0c;导致数据库语句可以做什么&#xff0c;用户就可以做什么。取决于不同数据库的不同查询语言&#xff0c;所以为什么有mysql注入/orcale注入等等。步骤&#xff1a;【access】表名&#xff08;字典爆破来…

机器人控制器开发(部署——软件打包备份更新)

文章总览 为什么做备份更新 为机器人控制器设计一套打包备份更新机制&#xff0c;为控制器的批量生产和产品与项目落地做准备。 当某个模块出现bug需要升级时&#xff0c;用户可以快速获取正确的bak包并导入到控制器中重启生效。 如果没有做好软件的备份更新机制&#xff0c…

LaTeX TeX Live 安装与 CTAN 国内镜像配置(Windows / macOS / Linux 全流程)

这是一份面向国内环境的 LaTeX 从零到可编译 指南&#xff1a;覆盖 TeX Live / MacTeX 安装、PATH 配置、CTAN 国内镜像&#xff08;清华/北外/上交/中科大等&#xff09;一键切换与回滚、常见坑位&#xff08;权限、镜像路径、版本切换&#xff09;、以及 XeLaTeX/latexmk 的实…

WhoisXML API再次荣登2025年美国Inc. 5000快速成长企业榜单

WhoisXML API非常自豪地宣布&#xff0c;我们再次荣登美国权威榜单——2025年Inc.5000全美成长最快的私营企业之一。今年&#xff0c;公司在地区排名中位列第119名&#xff0c;在全美总体排名中位列第4,271名。Inc. 5000榜单要求参评企业必须保持独立运营&#xff0c;并在2021至…

Elasticsearch面试精讲 Day 9:复合查询与过滤器优化

【Elasticsearch面试精讲 Day 9】复合查询与过滤器优化 在Elasticsearch的搜索体系中&#xff0c;复合查询&#xff08;Compound Queries&#xff09;与过滤器&#xff08;Filters&#xff09;优化是构建高效、精准搜索逻辑的核心能力。作为“Elasticsearch面试精讲”系列的第…

Android使用ReactiveNetwork监听网络连通性

引入库 implementation com.github.pwittchen:reactivenetwork-rx2:3.0.8监听网络连接变更ReactiveNetwork.observeNetworkConnectivity(context).subscribeOn(Schedulers.io())// ... // anything else what you can do with RxJava.observeOn(Schedulers.computation()).subs…

基于阿里云部署 RustDesk 自托管服务器

基于阿里云部署 RustDesk 自托管服务器一、背景与需求场景二、什么是 RustDesk&#xff1f;为什么选择自托管&#xff1f;2.1 RustDesk 是什么&#xff1f;2.2 为什么选择自托管&#xff1f;三、环境准备与架构说明四、操作步骤4.1 在阿里云上安装 RustDesk 服务端4.1.1 下载并…

细说分布式ID

针对高并发写&#xff0c;分布式ID是其业务基础&#xff0c;本文从一个面试题细细展开。面试官&#xff1a;1.对于Mysql的InnoDB引擎下&#xff0c;自增ID和UUID作为主键各自有什么优劣&#xff0c;对于一张表的主键你建议使用哪种ID&#xff1f;2.除了UUID是否还了解其他类型的…

2025年大数据专业证书报考指南:专科学历必看的8大选择​

对于大专学历的同学来说&#xff0c;2025年进入大数据行业是一个充满机遇的选择。大数据领域发展迅速&#xff0c;各类证书能够帮助求职者提升专业能力、增强就业竞争力。其中最推荐的是CDA数据分析师&#xff0c;这个证书适应了未来数字化经济和AI发展趋势&#xff0c;难度不高…

Python爬虫实战:研究Axis Artist模块,构建电商数据采集和分析系统

1. 引言 1.1 研究背景与意义 在大数据时代,互联网上蕴藏着海量有价值的信息,这些信息涵盖了社会、经济、科技等各个领域。高效地从互联网获取数据并进行深度分析,对于企业决策、学术研究、市场分析等都具有重要意义。Python 作为一种功能强大的编程语言,凭借其丰富的库支…

突破大语言模型推理瓶颈:深度解析依赖关系与优化策略

突破大语言模型推理瓶颈&#xff1a;深度解析依赖关系与优化策略当ChatGPT需要5秒才能生成一个回答&#xff0c;当企业级大模型每秒只能处理3个用户请求——这些性能瓶颈的背后&#xff0c;隐藏着大语言模型推理计算中复杂的依赖关系网。在大语言模型推理过程中&#xff0c;依赖…

整理了几道前端面试题

1. 若是有两个数组ar1和ar2&#xff0c;求它们的并集和交集&#xff0c;要怎么做&#xff1f; const ar1 [1, 2, 3, 4]; const ar2 [3, 4, 5, 6];一、求并集 (Union) 目标&#xff1a; 把两个数组合并成一个新数组&#xff0c;新数组包含所有出现过的元素&#xff0c;但每个…

Mac M4环境下基于VMware Fusion虚拟机安装Ubuntu24.04 LTS ARM版

Mac M4环境下基于VMware Fusion虚拟机安装Ubuntu24.04 LTS ARM版 1 下载Ubuntu镜像 在Ubuntu官网下载Ubuntu24.04 LTS的arm版镜像&#xff0c;这里选择ubuntu-24.04-live-server-arm64.iso&#xff0c;支持arm的似乎没有合适的desktop版本&#xff0c;Server版本默认是不带图…

开源与定制化对比:哪种在线教育系统源码更适合教育培训APP开发?

如今&#xff0c;“在线教育系统源码”已经成为许多教育培训机构、创业者甚至传统学校的高频关键词。无论是打造一款在线教育APP&#xff0c;还是开发企业内部培训平台&#xff0c;源码选择都决定了后续的开发效率、产品体验与商业化潜力。 在实际开发中&#xff0c;常见的源码…

中间件的日志分析

将日志文件access.log复制到kali中进行分析使用命令查看文件中各IP的访问次数&#xff0c;依次分析其行为awk { print $1 } access.log | sort | uniq -c |sort -nr172.16.3.189cat access.log | grep 172.16.3.198行为模式分析使用固定弱密码进行身份验证 几乎所有请求都使用用…