首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java 多线程与并发编程详解:原理、实现与实战

Java 多线程与并发编程详解:原理、实现与实战

原创
作者头像
用户11690575
发布2025-06-06 19:49:33
发布2025-06-06 19:49:33
70900
代码可运行
举报
运行总次数:0
代码可运行

一、引言:为什么要学习多线程?

随着 CPU 核心数的提升,单线程程序已无法充分发挥硬件性能。Java 提供了强大的并发编程支持,允许我们使用多线程来:

  • 提高程序执行效率
  • 响应多个用户请求(如 Web 服务)
  • 实现异步任务、并发数据处理
  • 构建高性能服务器和框架

二、线程基础

2.1 什么是线程?

线程(Thread)是进程中的最小执行单元,一个进程可以包含多个线程,多个线程共享进程的资源。

📌 线程 VS 进程:

对比项

进程

线程

定义

资源分配单位

CPU 执行单位

资源

独立资源空间

共享资源(如堆)

通信

开销大

更高效

开销

创建销毁开销大

开销较小


2.2 创建线程的方式

方式一:继承 Thread
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public class MyThread extends Thread {
    public void run() {
        System.out.println("线程运行:" + Thread.currentThread().getName());
    }
}
new MyThread().start();
方式二:实现 Runnable 接口
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Runnable 线程执行");
    }
}
new Thread(new MyRunnable()).start();
方式三:使用 Callable + Future
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑Callable<String> task = () -> {
    return "任务完成";
};
FutureTask<String> future = new FutureTask<>(task);
new Thread(future).start();
System.out.println(future.get());

三、线程的生命周期与状态图

📌 线程状态图如下:

代码语言:javascript
代码运行次数:0
运行
复制
sql复制编辑新建 NEW
  ↓
就绪 RUNNABLE ← 唤醒
  ↓
运行 RUNNING
  ↓    ↑
阻塞 BLOCKED/WAITING/TIMED_WAITING
  ↓
终止 TERMINATED

四、线程同步与锁机制

4.1 为什么需要同步?

多个线程同时访问共享资源时,可能产生“竞态条件”:

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑class Counter {
    int count = 0;
    public void add() {
        count++;
    }
}

多个线程同时调用 add(),可能导致最终 count 错误。


4.2 synchronized 同步关键字

修饰实例方法
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public synchronized void add() {
    count++;
}
修饰代码块
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public void add() {
    synchronized (this) {
        count++;
    }
}
修饰静态方法(类锁)
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public static synchronized void staticMethod() {}

📌 原理:

synchronized 会加锁对象的 monitor(监视器锁),底层依赖 JVM 实现。


4.3 死锁示例与避免

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public void deadlock() {
    synchronized (resourceA) {
        synchronized (resourceB) {
            // 死锁风险
        }
    }
}

避免方式:

  • 保持加锁顺序一致
  • 设置超时(如 tryLock()

五、常见并发工具类(Java.util.concurrent)

5.1 ReentrantLock(可重入锁)

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑Lock lock = new ReentrantLock();
try {
    lock.lock();
    // 临界区
} finally {
    lock.unlock();
}

📌 支持:

  • 公平锁 / 非公平锁
  • 可中断锁
  • 可重入
  • 条件变量(Condition)

5.2 CountDownLatch:等待多个线程完成

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑CountDownLatch latch = new CountDownLatch(3);

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 执行任务
        latch.countDown(); // 完成一次
    }).start();
}

latch.await(); // 等待3个线程执行完

5.3 CyclicBarrier:线程集合后统一执行

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("三线程到达,开始执行任务");
});

适合多个线程协作的场景,例如并行计算。


5.4 Semaphore:控制并发数

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑Semaphore semaphore = new Semaphore(3);
semaphore.acquire();
try {
    // 执行任务
} finally {
    semaphore.release();
}

控制访问资源的最大线程数,如连接池。


六、线程池详解(Executor 框架)

6.1 使用线程池的优势

  • 减少资源创建/销毁开销
  • 提高响应速度
  • 控制最大并发数

6.2 Executors 创建线程池

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(() -> {
    System.out.println("线程池任务执行");
});

📌 常见线程池类型:

类型

特点

newFixedThreadPool

固定线程数,适合稳定负载

newCachedThreadPool

自动扩容/回收线程,适合短任务

newSingleThreadPool

单线程,适合顺序执行

newScheduledPool

定时任务调度


6.3 自定义线程池参数(推荐)

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, 10,
    60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy()
);

📌 参数说明图解:

代码语言:javascript
代码运行次数:0
运行
复制
nginx复制编辑corePoolSize → 核心线程数
maximumPoolSize → 最大线程数
keepAliveTime → 空闲线程存活时间
workQueue → 任务队列
handler → 拒绝策略

七、线程安全集合类

7.1 常见类型

类名

描述

ConcurrentHashMap

线程安全的 HashMap

CopyOnWriteArrayList

读多写少的线程安全列表

BlockingQueue

支持阻塞的队列接口


八、volatile 与原子操作类

8.1 volatile:可见性关键字

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑volatile boolean running = true;

📌 保证线程间变量的 可见性,但不保证原子性。


8.2 原子类:AtomicInteger

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet(); // 原子自增

基于 CAS(Compare and Swap)机制实现无锁并发。


九、并发问题与调试技巧

9.1 经典并发问题

问题

说明

竞态条件

多线程抢占资源导致结果异常

死锁

线程互相等待资源,永不释放

饥饿

某线程长期得不到资源

活锁

不停改变状态但无法前进

9.2 常用调试工具与命令

  • jstack: 查看线程堆栈
  • VisualVM: 图形化分析工具
  • Java Flight Recorder: Java 性能监控

十、案例实战:模拟银行取款系统

代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑class Bank {
    private int balance = 1000;

    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            try { Thread.sleep(100); } catch (Exception e) {}
            balance -= amount;
            System.out.println(Thread.currentThread().getName() + " 取款成功,剩余:" + balance);
        } else {
            System.out.println(Thread.currentThread().getName() + " 余额不足");
        }
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
java复制编辑public class Test {
    public static void main(String[] args) {
        Bank bank = new Bank();
        Runnable r = () -> bank.withdraw(800);
        new Thread(r, "用户A").start();
        new Thread(r, "用户B").start();
    }
}

📌 观察输出结果并测试同步效果。


十一、总结与进阶方向

11.1 本文回顾要点:

  • 多线程基础与创建方式
  • 同步机制(synchronized、Lock)
  • 并发工具类(CountDownLatch、Semaphore 等)
  • 线程池与并发集合
  • volatile 与原子类
  • 并发调试方法

11.2 推荐进阶方向:

  • 学习 AQS(AbstractQueuedSynchronizer)原理
  • 掌握 Fork/Join 框架
  • 熟练使用 CompletableFuture 异步处理
  • 深入理解 Java 内存模型(JMM)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引言:为什么要学习多线程?
  • 二、线程基础
    • 2.1 什么是线程?
    • 2.2 创建线程的方式
      • 方式一:继承 Thread 类
      • 方式二:实现 Runnable 接口
      • 方式三:使用 Callable + Future
  • 三、线程的生命周期与状态图
  • 四、线程同步与锁机制
    • 4.1 为什么需要同步?
    • 4.2 synchronized 同步关键字
      • 修饰实例方法
      • 修饰代码块
      • 修饰静态方法(类锁)
    • 4.3 死锁示例与避免
  • 五、常见并发工具类(Java.util.concurrent)
    • 5.1 ReentrantLock(可重入锁)
    • 5.2 CountDownLatch:等待多个线程完成
    • 5.3 CyclicBarrier:线程集合后统一执行
    • 5.4 Semaphore:控制并发数
  • 六、线程池详解(Executor 框架)
    • 6.1 使用线程池的优势
    • 6.2 Executors 创建线程池
    • 6.3 自定义线程池参数(推荐)
  • 七、线程安全集合类
    • 7.1 常见类型
  • 八、volatile 与原子操作类
    • 8.1 volatile:可见性关键字
    • 8.2 原子类:AtomicInteger
  • 九、并发问题与调试技巧
    • 9.1 经典并发问题
    • 9.2 常用调试工具与命令
  • 十、案例实战:模拟银行取款系统
  • 十一、总结与进阶方向
    • 11.1 本文回顾要点:
    • 11.2 推荐进阶方向:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档