一、核心分类及常用类详解

1. 线程池相关(最核心,解决线程创建 / 销毁开销问题)

线程池是管理线程的容器,核心思想是复用线程,避免频繁创建销毁线程的性能损耗。

核心接口 / 类
类 / 接口 作用
Executor 最顶层接口,定义了线程执行的核心方法execute(Runnable)
ExecutorService 继承Executor,扩展了线程池的生命周期管理(关闭、提交任务等)
ThreadPoolExecutor 线程池的核心实现类(推荐直接使用,而非Executors工具类)
Executors 线程池工具类,提供快速创建线程池的静态方法(注意:生产环境慎用)
ScheduledExecutorService 定时任务线程池接口,支持延迟 / 周期性执行任务
关键说明 & 示例

ThreadPoolExecutor 核心参数(新手必懂):

// 核心构造方法(7个参数)
public ThreadPoolExecutor(
    int corePoolSize,        // 核心线程数(常驻线程,即使空闲也不销毁)
    int maximumPoolSize,     // 最大线程数(线程池能容纳的最大线程数)
    long keepAliveTime,      // 非核心线程空闲超时时间
    TimeUnit unit,           // 超时时间单位
    BlockingQueue<Runnable> workQueue, // 任务队列(核心线程满时存放任务)
    ThreadFactory threadFactory,       // 线程创建工厂(自定义线程名称/优先级)
    RejectedExecutionHandler handler   // 拒绝策略(任务满时的处理方式)
)

基础使用示例(生产环境推荐写法):

import java.util.concurrent.*;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 1. 自定义线程池(推荐)
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,                  // 核心线程数
            5,                  // 最大线程数
            60,                 // 非核心线程空闲60秒销毁
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10), // 有界任务队列(避免内存溢出)
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:主线程执行
        );

        // 2. 提交任务
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            executor.execute(() -> {
                System.out.println("任务" + taskId + "由线程" + Thread.currentThread().getName() + "执行");
                try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
            });
        }

        // 3. 关闭线程池(必须!否则程序不会退出)
        executor.shutdown();
    }
}

Executors 工具类的坑

  • newCachedThreadPool():无界线程池,可能创建大量线程导致 OOM;
  • newFixedThreadPool():任务队列无界,任务过多会 OOM;
  • 生产环境优先用ThreadPoolExecutor自定义参数,控制队列和线程数。

2. 锁相关(替代 synchronized,更灵活)

JUC 的锁基于Lock接口,相比synchronized(隐式锁),支持可中断、可超时、尝试获取锁、公平锁 / 非公平锁等特性。

核心类
作用
ReentrantLock 可重入锁(和 synchronized 一样,同一线程可重复获取锁),支持公平 / 非公平
ReentrantReadWriteLock 读写锁(读共享、写独占),适合读多写少场景,提升并发效率
示例:ReentrantLock(可中断锁)
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
    private static final ReentrantLock lock = new ReentrantLock(true); // 公平锁

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                // 尝试获取锁,5秒超时
                if (lock.tryLock(5, TimeUnit.SECONDS)) {
                    System.out.println("线程1获取锁成功");
                    Thread.sleep(3000); // 持有锁3秒
                } else {
                    System.out.println("线程1获取锁超时");
                }
            } catch (InterruptedException e) {
                System.out.println("线程1获取锁时被中断");
                Thread.currentThread().interrupt(); // 恢复中断状态
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock(); // 必须手动释放锁!
                    System.out.println("线程1释放锁");
                }
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                lock.lockInterruptibly(); // 可中断的锁获取
                System.out.println("线程2获取锁成功");
            } catch (InterruptedException e) {
                System.out.println("线程2获取锁时被中断");
                Thread.currentThread().interrupt();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                    System.out.println("线程2释放锁");
                }
            }
        });

        t1.start();
        t2.start();
        Thread.sleep(1000);
        t2.interrupt(); // 中断线程2的锁获取
    }
}
读写锁示例(读多写少场景)
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private static final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    private static final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
    private static int count = 0;

    // 读方法(共享锁)
    public static void read() {
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "读取count:" + count);
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readLock.unlock();
        }
    }

    // 写方法(独占锁)
    public static void write() {
        writeLock.lock();
        try {
            count++;
            System.out.println(Thread.currentThread().getName() + "写入count:" + count);
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        // 3个读线程(可同时执行)
        for (int i = 0; i < 3; i++) {
            new Thread(ReadWriteLockDemo::read, "读线程" + i).start();
        }
        // 1个写线程(独占,读线程需等待)
        new Thread(ReadWriteLockDemo::write, "写线程").start();
    }
}

3. 并发集合(线程安全,替代 Vector/Hashtable)

JUC 的并发集合相比传统线程安全集合(如 Vector),采用分段锁、CAS、写时复制等机制,并发效率更高。

核心类
作用 适用场景
ConcurrentHashMap 高效并发 Map(JDK1.8 用 CAS+Synchronized 替代分段锁) 高并发读写 Map
CopyOnWriteArrayList 写时复制列表(读无锁,写复制数组) 读多写少的列表场景
CopyOnWriteArraySet 基于 CopyOnWriteArrayList 实现的并发 Set 读多写少的 Set 场景
BlockingQueue 阻塞队列(核心接口,支持入队 / 出队阻塞) 生产者 - 消费者模型
ArrayBlockingQueue 有界数组阻塞队列(固定容量) 有界生产消费
LinkedBlockingQueue 链表阻塞队列(默认无界,可指定容量) 无界 / 有界生产消费
SynchronousQueue 同步队列(无存储,生产必须等消费) 线程池(newCachedThreadPool)
阻塞队列示例(生产者 - 消费者)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);

    // 生产者
    static class Producer implements Runnable {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    queue.put(i); // 队列满时阻塞
                    System.out.println("生产者生产:" + i + ",队列大小:" + queue.size());
                    Thread.sleep(200);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    // 消费者
    static class Consumer implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    Integer num = queue.take(); // 队列空时阻塞
                    System.out.println("消费者消费:" + num + ",队列大小:" + queue.size());
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new Producer()).start();
        new Thread(new Consumer()).start();
    }
}

4. 同步工具类(协调线程执行顺序)

用于控制多个线程之间的协作,比如等待所有线程完成、限制并发数等。

核心类
作用 核心区别
CountDownLatch 倒计时门闩(一个线程等待多个线程完成,计数减到 0 后唤醒) 计数只能减,不可重置
CyclicBarrier 循环栅栏(多个线程互相等待,都到达栅栏后一起执行,计数可重置) 可循环使用,支持屏障动作
Semaphore 信号量(控制同时访问资源的线程数,支持公平 / 非公平) 限流、控制并发数
Exchanger 交换器(两个线程交换数据,仅支持两个线程) 线程间数据交换
示例 1:CountDownLatch(等待所有子线程完成)
import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        int threadNum = 3;
        CountDownLatch latch = new CountDownLatch(threadNum); // 计数3

        for (int i = 0; i < threadNum; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "执行任务");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 计数减1
                    System.out.println(Thread.currentThread().getName() + "任务完成,剩余计数:" + latch.getCount());
                }
            }, "线程" + i).start();
        }

        latch.await(); // 主线程等待计数为0
        System.out.println("所有子线程完成,主线程继续执行");
    }
}
示例 2:Semaphore(限流)
import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    // 模拟只有2个停车位
    private static final Semaphore semaphore = new Semaphore(2);

    public static void main(String[] args) {
        // 模拟5辆车抢车位
        for (int i = 0; i < 5; i++) {
            int carNum = i;
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 获取许可(车位),无许可则阻塞
                    System.out.println("车辆" + carNum + "抢到车位");
                    Thread.sleep(2000); // 停车2秒
                    System.out.println("车辆" + carNum + "离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release(); // 释放许可
                }
            }).start();
        }
    }
}

5. 原子类(无锁并发,基于 CAS)

原子类通过CAS(Compare And Swap,比较并交换) 实现无锁并发,相比锁机制,减少了线程上下文切换的开销,适合简单变量的并发更新。

核心类
作用
AtomicInteger/AtomicLong 原子更新 int/long 类型变量
AtomicBoolean 原子更新 boolean 类型
AtomicReference 原子更新引用类型(对象)
AtomicStampedReference 原子更新引用类型,带版本号(解决 CAS 的 ABA 问题)
示例:AtomicInteger(无锁累加)
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {
    private static final AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                count.incrementAndGet(); // 原子自增(等价于count++,但线程安全)
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("最终计数:" + count.get()); // 输出2000(线程安全)
    }
}
ABA 问题说明:
  • 场景:线程 1 准备将变量从 A 改为 B,但线程 2 先将 A 改为 C,再改回 A,线程 1 的 CAS 会误以为值未变,更新成功;
  • 解决:AtomicStampedReference通过版本号(戳记)判断,只要版本号变了,即使值相同,CAS 也会失败。

二、总结

关键点回顾

  1. 核心分类:JUC 包常用类主要分为 5 类 —— 线程池、锁、并发集合、同步工具类、原子类,覆盖了并发编程的核心场景;
  2. 核心优势:相比传统并发方式(synchronized、Thread),JUC 提供了更高的并发效率(如 CAS、读写锁)、更灵活的控制(如可中断锁、超时锁)、更安全的工具(如有界阻塞队列);
  3. 使用原则
    • 线程池优先用ThreadPoolExecutor自定义参数,避免Executors的无界风险;
    • 读多写少用ReentrantReadWriteLock/CopyOnWriteArrayList,普通互斥用ReentrantLock
    • 简单变量并发更新用原子类,复杂同步用锁或同步工具类;
    • 生产消费模型优先用BlockingQueue
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐