多线程不再难懂!用生活例子讲透 Java 线程与并发工具

 一、多线程基础概念


进程 vs 线程

类型 定义 示例
进程 操作系统资源分配的基本单位 如一个 QQ 程序就是一个进程
线程 CPU 调度执行的基本单位 如 QQ 中的文字聊天、视频聊天是不同线程

️ 形象比喻:

进程 = 餐厅
线程 = 服务员
餐厅可以有多个服务员同时工作,但共享餐厅资源(如厨房、餐具)。

创建线程的三种方式
方式1:继承 Thread 类

class MyThread extends Thread {
    public void run() {
        System.out.println("我爱Java");
    }
}


方式2:实现 Runnable 接口

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Java也爱我");
    }
}


方式3:使用 Callable 和 Future

class MyCallable implements Callable {
    public String call() {
        return "双向奔赴的爱情";
    }
}


✅ 推荐方式:

使用 Runnable / Callable 可避免单继承限制
Callable 支持返回值和抛异常


二、线程状态与生命周期
 

线程在其生命周期中会经历以下 6种状态:

状态 描述
NEW 线程刚创建,尚未启动
RUNNABLE 线程正在运行或等待 CPU 时间片
BLOCKED 等待进入 synchronized 代码块/方法
WAITING 无限期等待其他线程唤醒
TIMED_WAITING 在指定时间内自动唤醒(如 sleep、wait(timeout))
TERMINATED 线程执行完毕或异常终止

形象比喻:
线程就像在玩滑梯:

NEW → 在排队准备上滑梯
RUNNABLE → 正在滑下来
BLOCKED → 滑梯口被别人占着了
WAITING → 在休息区等下次再玩
TIMED_WAITING → 看了眼手表,知道过会儿就能继续玩
TERMINATED → 家长喊回家吃饭了


三、线程同步与通信


1. synchronized 关键字
方法锁

public synchronized void method() {
    // 同步代码
}


代码块锁

synchronized(obj) {
    // 同步代码
}


2. Lock 接口(更灵活)

Lock lock = new ReentrantLock();
lock.lock();
try {
    // 执行代码
} finally {
    lock.unlock();
}


3. 线程间通信机制

synchronized(obj) {
    while (条件不满足) {
        obj.wait(); // 等待
    }
    // 执行操作
    obj.notifyAll(); // 唤醒其他线程
}


形象比喻:
线程通信就像情侣微信聊天:

wait() = “你先说...”
notify() = “收到!轮到我说了”
notifyAll() = 喊了一嗓子“开全体会议啦!”


四、线程池详解 ‍♀️


1. 四种常见线程池类型

ExecutorService pool = Executors.newFixedThreadPool(3); // 固定大小
ExecutorService pool = Executors.newCachedThreadPool(); // 缓存型(按需创建)
ExecutorService pool = Executors.newSingleThreadExecutor(); // 单线程
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2); // 调度型(支持定时任务)

2. 自定义线程池(推荐)

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, // 核心线程数
    10, // 最大线程数
    60, // 空闲线程存活时间
    TimeUnit.SECONDS, // 时间单位
    new LinkedBlockingQueue<>(100), // 工作队列
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);


形象比喻:
线程池就像外卖骑手团队:

核心骑手:常驻员工
临时骑手:高峰期加派人手
等待任务队列:排队处理的订单
拒绝策略:超负荷时怎么处理新订单


五、并发工具类
 

1. CountDownLatch(倒计时门闩)
适用于主线程等待多个子线程完成后再继续执行。

CountDownLatch latch = new CountDownLatch(3);

// 子线程调用
latch.countDown();

// 主线程等待
latch.await();


形象比喻:
就像火箭发射倒计时:"3...2...1...起飞!"

2. CyclicBarrier(循环屏障)
适用于多个线程相互等待,直到都到达某个屏障点后一起继续执行。

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("大家都到了,开始聚餐!");
});

barrier.await();

形象比喻:
就像朋友约饭:"小明到饭店了..."、"小红到饭店了..."、"小刚终于到了!上菜!" 

3. Semaphore(信号量)
用于控制同时访问的线程数量,常用于资源池管理、限流等场景。

Semaphore semaphore = new Semaphore(2); // 允许2个线程同时访问

semaphore.acquire(); // 获取许可
try {
    // 执行代码
} finally {
    semaphore.release(); // 释放许可
}

形象比喻:
就像停车场管理:"入口处取卡进场"、"出场还卡" 

六、总结 ✅

模块 核心内容
基础概念 进程与线程区别、创建线程的三种方式
线程状态 6种状态及转换流程
同步与通信 synchronized、ReentrantLock、wait/notify
线程池 内置线程池与自定义线程池配置
并发工具 CountDownLatch、CyclicBarrier、Semaphore

学习建议:

多写示例代码,动手实践是掌握并发的关键
结合日志调试观察线程切换和状态变化
实际项目中优先使用线程池 + FutureTask 或 CompletableFuture

你可能感兴趣的:(java,开发语言)