news 2026/1/11 18:06:27

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/1/6 19:19:38

隧道代理技术解析:它为何成为数据安全传输的首选?

在金融交易、医疗数据传输、企业内网访问等场景中&#xff0c;“数据安全”从来都是不可逾越的红线。传统代理频繁出现的明文传输、连接劫持、IP泄露等问题&#xff0c;让企业在数字化转型中如履薄冰。而隧道代理的崛起&#xff0c;恰好为数据安全传输提供了一套完整的解决方案…

作者头像 李华
网站建设 2026/1/7 2:31:17

从地面站到太空节点,卫星Agent信号处理全流程拆解,不容错过

第一章&#xff1a;卫星Agent信号处理概述 在现代空间通信系统中&#xff0c;卫星Agent作为数据采集与中继的核心单元&#xff0c;承担着接收、处理和转发多源异构信号的关键任务。这些Agent通常部署于低轨&#xff08;LEO&#xff09;或地球同步轨道&#xff08;GEO&#xff0…

作者头像 李华
网站建设 2026/1/11 11:17:51

【RT-DETR涨点改进】独家创新首发、Neck特征融合改进篇 | TGRS 2025顶刊 | RT-DETR引入HFFE高低频特征融合模块,增强多层次特征融合、噪声抑制,助力目标检测有效涨点

一、本文介绍 🔥本文给大家介绍使用HFFE高低频特征融合模块改进RT-DETR网络模型,能够显著提升目标检测性能。HFFE通过引入层次化特征融合和注意力机制,优化了多尺度特征的融合,增强了小目标的检测精度和定位准确性,特别是在复杂背景和低质量图像中。此外,HFFE有效抑制了…

作者头像 李华
网站建设 2026/1/6 2:30:41

【荐书】掌握LLM,全套方法就在这本书里

Part.1 AI工程师都要会些什么&#xff1f; 大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;技术的兴起&#xff0c;正在深刻影响软件的形态&#xff0c;开发者的工作也从实现业务逻辑、构建独立应用&#xff0c;转向以LLM为底层引擎快速搭建智能应用的…

作者头像 李华