news 2026/6/10 13:11:28

java多线程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java多线程

一、先搞懂:什么是 Java 多线程?

可以把进程想象成一个正在运行的应用程序(比如你的微信),而线程是进程里的最小执行单元(比如微信同时处理接收消息、显示界面、播放语音)。Java 多线程就是让一个 Java 程序同时执行多个任务,充分利用 CPU 资源,提升程序运行效率(比如下载文件时,一个线程下载、一个线程显示进度、一个线程校验文件)。

二、Java 多线程的 3 种核心实现方式

方式 1:继承 Thread 类(最基础)

Thread 类是 Java 封装好的线程类,继承它并重写run()方法(线程要执行的任务),调用start()启动线程(注意:不能直接调用run(),否则只是普通方法调用)。

java

运行

// 步骤1:继承Thread类 class MyThread extends Thread { // 步骤2:重写run()方法,定义线程任务 @Override public void run() { for (int i = 0; i < 5; i++) { // Thread.currentThread().getName()获取当前线程名称 System.out.println(Thread.currentThread().getName() + " 执行:" + i); try { Thread.sleep(100); // 线程休眠100ms,模拟任务耗时 } catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadDemo { public static void main(String[] args) { // 步骤3:创建线程对象并启动 MyThread thread1 = new MyThread(); thread1.setName("线程1"); thread1.start(); // 启动线程1 MyThread thread2 = new MyThread(); thread2.setName("线程2"); thread2.start(); // 启动线程2 } }

输出效果(线程 1 和线程 2 交替执行,顺序不固定,因为 CPU 调度是随机的):

plaintext

线程1 执行:0 线程2 执行:0 线程1 执行:1 线程2 执行:1 ...
方式 2:实现 Runnable 接口(推荐,避免单继承限制)

Java 是单继承,所以更推荐实现Runnable接口(只定义run()方法),再把 Runnable 对象传给 Thread 类启动。

java

运行

// 步骤1:实现Runnable接口 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(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class RunnableDemo { public static void main(String[] args) { // 步骤2:创建Runnable任务对象 MyRunnable task = new MyRunnable(); // 步骤3:将任务传给Thread并启动 Thread thread1 = new Thread(task, "线程A"); thread1.start(); Thread thread2 = new Thread(task, "线程B"); thread2.start(); } }
方式 3:实现 Callable 接口(带返回值 + 可抛异常)

前两种方式没有返回值,Callable接口支持线程执行完返回结果,搭配FutureTask获取结果。

java

运行

import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; // 步骤1:实现Callable接口,指定返回值类型(这里是Integer) class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 1; i <= 100; i++) { sum += i; } return sum; // 线程执行结果 } } public class CallableDemo { public static void main(String[] args) throws Exception { // 步骤2:创建Callable任务 MyCallable callable = new MyCallable(); FutureTask<Integer> futureTask = new FutureTask<>(callable); // 步骤3:启动线程 Thread thread = new Thread(futureTask); thread.start(); // 步骤4:获取线程执行结果(get()会阻塞,直到线程执行完成) Integer result = futureTask.get(); System.out.println("线程执行结果:1-100求和 = " + result); // 输出5050 } }

三、多线程核心问题:线程安全

多个线程同时操作共享数据时,会出现数据错乱(比如两个线程同时给一个变量加 1,结果可能不是预期值)。

解决方法:加锁(synchronized)

java

运行

// 共享资源类 class Counter { private int count = 0; // 加synchronized关键字,保证同一时间只有一个线程执行该方法 public synchronized void increment() { count++; } public int getCount() { return count; } } // 线程任务:调用increment() class CounterTask implements Runnable { private Counter counter; public CounterTask(Counter counter) { this.counter = counter; } @Override public void run() { for (int i = 0; i < 1000; i++) { counter.increment(); } } } public class ThreadSafeDemo { public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); // 两个线程操作同一个Counter对象 Thread t1 = new Thread(new CounterTask(counter)); Thread t2 = new Thread(new CounterTask(counter)); t1.start(); t2.start(); // 等待两个线程执行完成 t1.join(); t2.join(); System.out.println("最终计数:" + counter.getCount()); // 正确输出2000(不加锁可能小于2000) } }

四、Java 多线程常用工具(JUC 包,新手入门核心)

Java 提供了java.util.concurrent(JUC)包,简化多线程开发,核心工具:

  1. 线程池(ExecutorService):避免频繁创建 / 销毁线程的开销,复用线程执行任务

    java

    运行

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // 创建固定大小的线程池(2个线程) ExecutorService pool = Executors.newFixedThreadPool(2); // 提交3个任务,线程池会复用2个线程执行 pool.submit(() -> System.out.println(Thread.currentThread().getName() + " 执行任务1")); pool.submit(() -> System.out.println(Thread.currentThread().getName() + " 执行任务2")); pool.submit(() -> System.out.println(Thread.currentThread().getName() + " 执行任务3")); pool.shutdown(); // 关闭线程池 } }
  2. Lock 锁:比synchronized更灵活(支持手动加锁 / 解锁、可中断、超时等待)
  3. CountDownLatch:等待多个线程执行完成后,主线程再继续(比如等待所有下载线程完成,再合并文件)

五、多线程常见坑点 & 注意事项

  1. 线程启动错误:调用run()而非start(),导致没有创建新线程,只是主线程执行方法。
  2. 线程安全问题:未加锁操作共享数据,导致数据不一致(比如电商库存超卖)。
  3. 线程死锁:两个线程互相持有对方需要的锁,导致都无法执行(比如线程 1 拿锁 A 等锁 B,线程 2 拿锁 B 等锁 A)。
  4. 过度创建线程:线程数超过 CPU 核心数太多,会导致线程切换开销过大,反而降低效率。

六、实战场景:什么时候用多线程?

  • 耗时操作(下载、文件读写、网络请求):单独开线程,避免主线程阻塞(比如 GUI 程序卡界面)。
  • 批量处理任务(批量导入数据、批量生成报表):用线程池并行处理,提升效率。
  • 实时性要求高的场景(秒杀系统、实时监控):多线程同时处理请求。

总结

  1. Java 多线程核心是让程序并行执行多个任务,核心实现方式有继承 Thread实现 Runnable(推荐)、实现 Callable(带返回值),启动线程必须调用start()
  2. 多线程操作共享数据时,必须通过synchronized或 Lock 保证线程安全,避免数据错乱。
  3. 实际开发中优先使用 JUC 包的线程池(复用线程)、CountDownLatch等工具,减少手动管理线程的复杂度,规避死锁、过度创建线程等问题。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 2:02:59

Git命令速查手册:从入门到精通

常用Git命令清单一般来说&#xff0c;日常使用只要记住下图6个命令&#xff0c;就可以了。但是熟练使用&#xff0c;恐怕要记住60&#xff5e;100个命令。下面是整理的常用 Git 命令清单。几个专用名词的译名如下。Workspace&#xff1a;工作区Index / Stage&#xff1a;暂存区…

作者头像 李华
网站建设 2026/6/10 14:52:14

【必收藏】大模型学习全攻略:从小白到AI工程师的进阶之路

记得曾经有人说过这样一个俗语&#xff1a;三百六十行&#xff0c;行行转IT。 或许听到这个话的时候会觉得是一句玩笑话&#xff0c;但是浏览到网络上一些关于就业的文章&#xff0c;就能够明白这句话的真正意义所在。随着互联网的发展&#xff0c;越来越多人选择&#xff0c;…

作者头像 李华
网站建设 2026/6/10 14:47:42

为什么你的物流Agent总是超时?:基于百万级订单验证的7大调优技巧

第一章&#xff1a;物流运输 Agent 的时效保证在现代物流系统中&#xff0c;运输时效是衡量服务质量的核心指标之一。物流运输 Agent 作为智能调度与路径优化的关键组件&#xff0c;通过实时数据感知、动态资源调配和预测性决策&#xff0c;显著提升了运输过程的可控性与时效稳…

作者头像 李华
网站建设 2026/6/10 12:33:42

疾控实验室信息系统选型指南:需求分析与实践路径

一、疾控实验室信息系统需求分析1.1 功能需求疾控实验室信息系统&#xff08;LIMS&#xff09;的核心功能需求需覆盖日常检测与应急响应两大场景。在日常检测流程中&#xff0c;系统需支持样本接收、检测任务分配、结果录入与审核、报告生成等全流程自动化管理&#xff0c;实现…

作者头像 李华