Java多线程编程:从基础到实战的完整指南

引言:为什么需要多线程?

在当今多核处理器普及的时代,充分利用计算资源已成为提升程序性能的关键。Java多线程允许程序同时执行多个任务,显著提高应用程序的响应速度和处理能力。无论是Web服务器处理并发请求,还是大数据处理中的并行计算,多线程技术都扮演着重要角色。

一、线程基础概念

1.1 进程与线程的区别

// 简单比喻:进程是工厂,线程是工厂中的流水线 public class ProcessVsThread { public static void main(String[] args) { // 进程:拥有独立的内存空间 // 线程:共享进程的内存空间,轻量级执行单元 System.out.println("进程 - 独立内存空间,重量级"); System.out.println("线程 - 共享内存空间,轻量级"); } }

1.2 Java线程的生命周期

新建(New) → 就绪(Runnable) → 运行(Running) → 阻塞(Blocked) ↓ ↑ └────── 等待(Waiting) ←──────┘ ↓ 超时等待(Timed Waiting) ↓ 终止(Terminated)

二、创建线程的三种方式

2.1 继承Thread类(不推荐)只能继承一个类

public class MyThread extends Thread { @Override public void run() { System.out.println("线程执行: " + Thread.currentThread().getName()); } public static void main(String[] args) { MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); thread1.start(); // 启动线程 thread2.start(); } }

2.2 实现Runnable接口(推荐)可以有多个接口也能继承类

public class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + ": " + i); try { Thread.sleep(500); // 模拟耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Thread thread1 = new Thread(new MyRunnable(), "线程A"); Thread thread2 = new Thread(new MyRunnable(), "线程B"); thread1.start(); thread2.start(); } }

2.3 实现Callable接口(带返回值)

import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class MyCallable implements Callable<Integer> { private final int number; public MyCallable(int number) { this.number = number; } @Override public Integer call() throws Exception { System.out.println("计算中... " + Thread.currentThread().getName()); Thread.sleep(1000); return number * number; // 返回计算结果 } public static void main(String[] args) throws Exception { FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable(5)); Thread thread = new Thread(futureTask, "计算线程"); thread.start(); // 获取计算结果(会阻塞直到计算完成) Integer result = futureTask.get(); System.out.println("计算结果: " + result); } }

三、线程同步与线程安全

3.1 同步问题示例:银行取款

public class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } // 线程不安全的方法 public void unsafeWithdraw(double amount) { if (balance >= amount) { try { Thread.sleep(100); // 模拟处理时间 } catch (InterruptedException e) { e.printStackTrace(); } balance -= amount; System.out.println(Thread.currentThread().getName() + " 取款 " + amount + ",余额: " + balance); } } // 使用synchronized保证线程安全 public synchronized void safeWithdraw(double amount) { if (balance >= amount) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } balance -= amount; System.out.println(Thread.currentThread().getName() + " 取款 " + amount + ",余额: " + balance); } } }

3.2 同步方法对比

public class SynchronizationDemo { private int counter = 0; // 1. 同步实例方法 public synchronized void incrementSyncMethod() { counter++; } // 2. 同步代码块 public void incrementSyncBlock() { synchronized(this) { counter++; } } // 3. 同步静态方法 public static synchronized void staticSyncMethod() { // 类级别的锁 } // 4. 使用Lock对象(更灵活) private final Lock lock = new ReentrantLock(); public void incrementWithLock() { lock.lock(); try { counter++; } finally { lock.unlock(); // 确保锁被释放 } } }

3.3 volatile关键字

public class VolatileDemo { // volatile保证可见性,不保证原子性 private volatile boolean flag = true; public void stop() { flag = false; } public void work() { while (flag) { // 工作逻辑 } System.out.println("线程停止"); } }

四、线程间通信

4.1 wait() 和 notify() 机制

public class ProducerConsumerExample { private final List<Integer> buffer = new LinkedList<>(); private final int CAPACITY = 5; public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { // 缓冲区满时等待 while (buffer.size() == CAPACITY) { wait(); } System.out.println("生产: " + value); buffer.add(value++); // 通知消费者 notify(); Thread.sleep(1000); } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { // 缓冲区空时等待 while (buffer.isEmpty()) { wait(); } int value = buffer.remove(0); System.out.println("消费: " + value); // 通知生产者 notify(); Thread.sleep(1000); } } } }

五、线程池(Thread Pool)

5.1 Executors工具类

import java.util.concurrent.*; public class ThreadPoolDemo { public static void main(String[] args) { // 1. 固定大小线程池 ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 2. 单线程线程池 ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); // 3. 缓存线程池 ExecutorService cachedPool = Executors.newCachedThreadPool(); // 4. 定时任务线程池 ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3); // 提交任务 for (int i = 0; i < 10; i++) { final int taskId = i; fixedPool.execute(() -> { System.out.println("执行任务 " + taskId + ",线程: " + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } // 优雅关闭线程池 fixedPool.shutdown(); try { if (!fixedPool.awaitTermination(60, TimeUnit.SECONDS)) { fixedPool.shutdownNow(); } } catch (InterruptedException e) { fixedPool.shutdownNow(); } } }

5.2 自定义线程池

public class CustomThreadPool { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 5, // 最大线程数 60L, // 空闲线程存活时间 TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), // 任务队列 Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 ); // 监控线程池状态 ScheduledExecutorService monitor = Executors.newScheduledThreadPool(1); monitor.scheduleAtFixedRate(() -> { System.out.println("活跃线程数: " + executor.getActiveCount()); System.out.println("队列大小: " + executor.getQueue().size()); System.out.println("完成任务数: " + executor.getCompletedTaskCount()); }, 0, 1, TimeUnit.SECONDS); } }

六、高级并发工具类

6.1 CountDownLatch(倒计时门闩)

public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { int workerCount = 5; CountDownLatch startLatch = new CountDownLatch(1); CountDownLatch endLatch = new CountDownLatch(workerCount); for (int i = 0; i < workerCount; i++) { new Thread(() -> { try { startLatch.await(); // 等待开始信号 System.out.println(Thread.currentThread().getName() + " 开始工作"); Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread.currentThread().getName() + " 完成工作"); endLatch.countDown(); // 任务完成 } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } System.out.println("准备开始所有工作..."); Thread.sleep(1000); startLatch.countDown(); // 发出开始信号 endLatch.await(); // 等待所有任务完成 System.out.println("所有工作完成!"); } }

6.2 CyclicBarrier(循环屏障)

public class CyclicBarrierDemo { public static void main(String[] args) { int threadCount = 3; CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> System.out.println("所有线程到达屏障,继续执行")); for (int i = 0; i < threadCount; i++) { final int threadId = i; new Thread(() -> { try { System.out.println("线程" + threadId + " 准备阶段1"); Thread.sleep(1000); barrier.await(); System.out.println("线程" + threadId + " 准备阶段2"); Thread.sleep(1000); barrier.await(); System.out.println("线程" + threadId + " 完成"); } catch (Exception e) { e.printStackTrace(); } }).start(); } } }

6.3 Semaphore(信号量)

public class SemaphoreDemo { public static void main(String[] args) { // 模拟3个停车位 Semaphore semaphore = new Semaphore(3); // 10辆车需要停车 for (int i = 1; i <= 10; i++) { final int carId = i; new Thread(() -> { try { System.out.println("车辆" + carId + " 等待停车"); semaphore.acquire(); System.out.println("车辆" + carId + " 停车成功"); Thread.sleep(2000); // 停车时间 System.out.println("车辆" + carId + " 离开"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }

七、并发集合

7.1 常用并发集合类

public class ConcurrentCollections { public static void main(String[] args) { // 1. ConcurrentHashMap(线程安全的HashMap) ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>(); concurrentMap.put("key1", 1); concurrentMap.putIfAbsent("key1", 2); // 不存在时才添加 // 2. CopyOnWriteArrayList(读多写少的场景) CopyOnWriteArrayList<String> copyOnWriteList = new CopyOnWriteArrayList<>(); copyOnWriteList.add("item1"); copyOnWriteList.addIfAbsent("item1"); // 线程安全的添加 // 3. ConcurrentLinkedQueue(无界线程安全队列) ConcurrentLinkedQueue<String> concurrentQueue = new ConcurrentLinkedQueue<>(); concurrentQueue.offer("task1"); String task = concurrentQueue.poll(); // 4. BlockingQueue(阻塞队列) BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10); try { blockingQueue.put("element"); // 阻塞直到有空间 String element = blockingQueue.take(); // 阻塞直到有元素 } catch (InterruptedException e) { e.printStackTrace(); } } }

八、最佳实践与常见问题

8.1 多线程最佳实践

public class BestPractices { // 1. 使用线程池而不是直接创建线程 private final ExecutorService executor = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() ); // 2. 使用局部变量,避免共享状态 public void process() { String localVariable = "安全"; // 线程安全 // ... } // 3. 使用不可变对象 public final class ImmutablePerson { private final String name; private final int age; public ImmutablePerson(String name, int age) { this.name = name; this.age = age; } // 只有getter,没有setter } // 4. 避免死锁 public void avoidDeadlock() { // 按固定顺序获取锁 Object lock1 = new Object(); Object lock2 = new Object(); Thread thread1 = new Thread(() -> { synchronized (lock1) { try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (lock2) { // 操作 } } }); Thread thread2 = new Thread(() -> { synchronized (lock1) { // 与thread1相同的顺序 try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (lock2) { // 操作 } } }); } }

8.2 常见问题与调试

public class ThreadDebugging { // 1. 线程死锁检测 public static void detectDeadlock() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadMXBean.findDeadlockedThreads(); if (threadIds != null) { ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds); for (ThreadInfo threadInfo : threadInfos) { System.out.println("死锁线程: " + threadInfo.getThreadName()); } } } // 2. 线程堆栈分析 public static void printAllStackTraces() { Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces(); for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) { Thread thread = entry.getKey(); System.out.println("\n线程: " + thread.getName() + " - 状态: " + thread.getState()); for (StackTraceElement element : entry.getValue()) { System.out.println(" " + element); } } } // 3. 使用ThreadLocal private static final ThreadLocal<SimpleDateFormat> dateFormatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd")); public static String formatDate(Date date) { return dateFormatter.get().format(date); } }

九、CompletableFuture(Java 8+)

public class CompletableFutureDemo { public static void main(String[] args) throws Exception { // 1. 创建异步任务 CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "结果1"; }); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return "结果2"; }); // 2. 组合多个Future CompletableFuture<String> combined = future1.thenCombine(future2, (result1, result2) -> result1 + " + " + result2); // 3. 异步回调 combined.thenAccept(result -> { System.out.println("最终结果: " + result); }); // 4. 异常处理 CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("模拟异常"); } return "成功"; }).exceptionally(ex -> { System.out.println("处理异常: " + ex.getMessage()); return "默认值"; }); // 等待所有任务完成 CompletableFuture.allOf(future1, future2).join(); } }

十、实战案例:并发下载器

public class ConcurrentDownloader { private final ExecutorService executor; private final int maxConcurrentDownloads; public ConcurrentDownloader(int maxConcurrentDownloads) { this.maxConcurrentDownloads = maxConcurrentDownloads; this.executor = Executors.newFixedThreadPool(maxConcurrentDownloads); } public void downloadFiles(List<String> urls) { CountDownLatch latch = new CountDownLatch(urls.size()); List<Future<File>> futures = new ArrayList<>(); for (String url : urls) { Callable<File> downloadTask = () -> { try { System.out.println("开始下载: " + url); // 模拟下载过程 Thread.sleep((long) (Math.random() * 3000)); System.out.println("下载完成: " + url); return new File(url.substring(url.lastIndexOf('/') + 1)); } finally { latch.countDown(); } }; futures.add(executor.submit(downloadTask)); } try { // 等待所有下载完成 latch.await(); System.out.println("所有文件下载完成"); // 处理下载结果 for (Future<File> future : futures) { try { File file = future.get(); // 处理文件 } catch (ExecutionException e) { System.err.println("下载失败: " + e.getCause()); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public void shutdown() { executor.shutdown(); try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); } } }

结语

Java多线程编程是一个强大但需要谨慎使用的工具。掌握多线程技术需要理解:

  1. 基础概念:线程生命周期、同步机制

  2. 高级特性:线程池、并发工具类

  3. 最佳实践:避免死锁、减少锁竞争

  4. 调试技巧:分析线程转储、监控线程状态

在实际开发中,建议:

  • 优先使用高层并发工具(如Executor框架)

  • 尽量使用不可变对象和线程安全集合

  • 合理设置线程池参数

  • 编写可测试的并发代码

记住:始终将线程安全放在首位。

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

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

相关文章

吐血推荐!专科生必用AI论文网站TOP9:开题报告全攻略

吐血推荐&#xff01;专科生必用AI论文网站TOP9&#xff1a;开题报告全攻略 2026年专科生AI论文写作工具测评&#xff1a;精准选型指南 随着人工智能技术的不断进步&#xff0c;AI论文写作工具逐渐成为高校学生&#xff0c;尤其是专科生撰写论文的重要辅助。然而&#xff0c;面…

RTX 5090 是 AI 开发者的合适选择吗?

传送锚点1. RTX 5090 实际上在多大程度上提升了 AI 工作负载&#xff1f;1.1 32GB 显存是突破吗&#xff1f;2. 开发者必须升级哪些设备才能安全运行 5090&#xff1f;2.1 功率输送需求2.2 冷却与底盘集成2.3 存储需求3. 框架准备好应对 5090 了吗&#xff1f;3.1 Linux&#x…

AI视频生成提速200倍:TurboDiffusion如何让一小时的等待缩短至几十秒?

传送锚点1.0 引言&#xff1a;当AI视频创作不再需要漫长等待2.0 核心看点&#xff1a;四项关键洞察2.1 看点一&#xff1a;令人惊叹的200倍速度飞跃2.2 看点二&#xff1a;速度的秘诀——“组合拳”式的技术优化2.3 看点三&#xff1a;速度与画质兼得&#xff0c;打破“非此即彼…

世界模型正在掀起AI新浪潮

传送锚点全新架构重构计算范式自动化系统的训练场谁将复制出下一个Flash获取方式全新架构重构计算范式 谷歌最新发布的Gemini 3 Flash&#xff0c;从命名方式来看似乎是双子座3家族中一个“轻量”版本。但真正的不同之处不止是体积或速度&#xff0c;而是一种计算范式的转变。…

AI驱动下的武汉GEO优化服务商全景:干货解析与优质选择 - 品牌评测官

随着生成式AI搜索的普及,GEO(生成式引擎优化)已替代传统SEO成为企业数字营销的核心赛道。武汉作为中部数字经济枢纽,凭借跨境电商爆发与政策红利,形成了极具特色的GEO服务生态。本文将先拆解GEO优化的核心逻辑与行…

2026环氧树脂绝缘板厂家权威推荐榜单:环氧树脂绝缘管/螺栓绝缘套管/螺栓绝缘帽/环氧树脂绝缘螺栓/树脂绝缘板源头厂家精选。 - 品牌推荐官

在电机、电器设备及变压器等工业领域,绝缘材料是保障设备稳定运行的核心组件。随着行业对绝缘性能要求的持续提升,具备高耐温、阻燃、防静电等特性的环氧树脂绝缘材料逐渐成为主流选择。本文聚焦环氧树脂绝缘材料领域…

2026年评价高的昆明民航路仓库出租,昆明官渡区仓库出租,昆明仓库出租公司选购决策指南 - 品牌鉴赏师

引言在当今物流与商业蓬勃发展的时代,昆明的仓库出租市场愈发繁荣,为众多企业提供了重要的仓储支持。尤其是昆明民航路仓库出租、昆明官渡区仓库出租等细分领域,满足了不同企业多样化的仓储需求。为了帮助企业在众多…

2026年国内知名的全自动超声波清洗机厂家推荐榜,工件超声波清洗机/工业超声波清洗设备,全自动超声波清洗机工厂电话 - 品牌推荐师

行业背景:清洗技术升级驱动制造业效率革命 随着工业4.0与“双碳”目标的推进,制造业对精密清洗的需求持续攀升。全自动超声波清洗机凭借高效、环保、一致性的优势,成为汽车零部件、半导体、新能源等领域的核心设备。…

收集自己的每日早餐花费,统计每周平均早餐费用,输出最经济的早餐搭配建议。

完整输出一个可运行的 Python 项目示例&#xff0c;用于收集每日早餐花费、统计每周平均早餐费用、输出最经济的早餐搭配建议。1. 实际应用场景描述在快节奏的生活中&#xff0c;很多人习惯在外购买早餐&#xff0c;但往往对每天的花费缺乏记录&#xff0c;导致月底发现餐饮支出…

2026沃尔玛购物卡回收高效操作攻略! - 淘淘收小程序

你是否曾收到沃尔玛购物卡后满心欢喜,却因忙碌或消费习惯差异,让卡片在角落闲置许久?我就有过这样的经历,本计划用购物卡采购好物,却因工作繁忙将其遗忘,等想起时已闲置数月。 生活中这类情况十分常见,节日礼物…

口碑不错的AI搜索优化企业有哪些,哪家性价比高? - 工业品牌热点

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家标杆企业,为ToB企业选型提供客观依据,助力精准匹配适配的AI搜索优化服务伙伴。 TOP1 推荐:南方网通 推荐指数:★★★★★ | 口碑评分:国内专业的AI搜索优…

杭州拼多多代运营公司排名:2026年最新服务商参考榜 - 前沿公社

本文结合市场排行、行业口碑与服务能力评估,为杭州地区的拼多多代运营公司建立一个多维度评分参考体系,帮助商家在选择合作伙伴时能更快速判断适配度。 一、评分依据说明 本参考榜单并非拼多多官方排名,而是基于以下…

PW1515 DEMO板核

PW1515是一款专为保护精密后端电路而设计的高性能、可编程过压过流保护芯片。在当今复杂的电子系统中,电源路径时常面临电压浪涌、负载短路等潜在风险,PW1515充当着系统“安全卫士”的关键角色。它通过监测输入电压与…

Java版LeetCode热题100之翻转二叉树:从递归到迭代的全面解析

Java版LeetCode热题100之翻转二叉树&#xff1a;从递归到迭代的全面解析本文将深入剖析 LeetCode 第226题「翻转二叉树」&#xff0c;不仅提供递归与迭代两种主流解法&#xff0c;还涵盖算法原理、复杂度分析、面试技巧、工程应用及关联题目拓展。全文约9500字&#xff0c;结构…

互联网大厂Java小白求职:音视频场景下的技术面试指南

场景设定 在一家互联网大厂的音视频研发部门&#xff0c;超好吃是一位初入职场的Java程序员&#xff0c;正在接受严肃的面试官的技术面试。这次面试涉及到音视频场景的相关技术点。第一轮提问&#xff1a;基础技术点 面试官&#xff1a;超好吃&#xff0c;Java语言是你的核心技…

2025园区招商趋势前瞻:实战经验分享,园区/办公场地/企业独栋,园区招商买卖排行榜 - 品牌推荐师

随着城市化进程加速与产业升级需求激增,2025年园区招商领域正经历深刻变革。从单一物业租赁向“产业+生态+服务”综合运营转型,园区需通过精准定位、资源整合与差异化服务构建竞争力。据第三方机构统计,全国园区空置…

Java版LeetCode热题100之对称二叉树:从递归到迭代的深度解析

Java版LeetCode热题100之对称二叉树&#xff1a;从递归到迭代的深度解析本文将全面、深入地剖析 LeetCode 第101题「对称二叉树」&#xff0c;不仅提供递归与迭代两种主流解法&#xff0c;还涵盖算法原理、复杂度分析、面试技巧、工程应用及关联题目拓展。全文约9500字&#xf…

Android 线程梳理

Android 线程梳理 Android 进程梳理 APP 进程的线程 Heap thread poo 异步的HeapWorker, 包含5个Signal Catcher 捕捉Kernel信号&#xff0c;比如SIGNAL_QUITJDWP 虚拟机调试的线程ReferenceQueueD 用于GCFinalizerDaemon 用于GCFinalizerWatchd 用于GCHeapTrimmerDaem 用于G…

HTML与CSS核心概念详解

一、HTML&#xff1a;超文本标记语言 什么是“超文本”&#xff1f; 超文本&#xff08;HyperText&#xff09; 的核心是“链接”。传统文本是线性的&#xff08;像一本书&#xff0c;一页接一页&#xff09;&#xff0c;而超文本通过可点击的链接&#xff0c;让信息能够非线…

Java实习模拟面试复盘:深入HashMap线程安全、Spring Boot核心机制与分布式系统设计(实在智能终面45分钟)

Java实习模拟面试复盘&#xff1a;深入HashMap线程安全、Spring Boot核心机制与分布式系统设计&#xff08;实在智能终面45分钟&#xff09;关键词&#xff1a;Java面试 | HashMap | 线程安全 | Spring Boot | 分布式ID | JWT鉴权在近期参加的实在智能公司Java开发工程师终面中…