Java多线程与并发编程全面解析:从基础到高级实践

Java多线程与并发编程全面解析:从基础到高级实践

一、Java多线程基础类

1.1 核心线程类

Java多线程编程的核心类主要包括:

  • Thread:线程类,继承Thread类并重写run()方法
  • Runnable:函数式接口,实现run()方法,无返回值
  • Callable:函数式接口,实现call()方法,有返回值
  • Future:异步计算结果接口,用于获取Callable的返回值

1.2 线程状态

Java线程的生命周期包含6种状态:

  • NEW:新建状态,线程对象已创建但未启动
  • RUNNABLE:可运行状态,包括就绪和运行中
  • BLOCKED:阻塞状态,等待获取监视器锁
  • WAITING:无限期等待,需要其他线程显式唤醒
  • TIMED_WAITING:限期等待,超时后自动唤醒
  • TERMINATED:终止状态,线程执行完毕

二、线程池核心机制

2.1 ThreadPoolExecutor

Java线程池的核心实现类,提供灵活的线程池配置:

ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, // 核心线程数 maximumPoolSize, // 最大线程数 keepAliveTime, // 空闲线程存活时间 TimeUnit.SECONDS, // 时间单位 workQueue, // 阻塞队列 threadFactory, // 线程工厂 handler // 拒绝策略 );

2.2 Executors工具类

Executors提供了4种常用的线程池创建方法:

  • newFixedThreadPool:固定大小线程池
  • newCachedThreadPool:可缓存线程池,自动回收空闲线程
  • newSingleThreadExecutor:单线程线程池
  • newScheduledThreadPool:定时任务线程池

2.3 ForkJoinPool

专为分治任务设计的线程池,适用于CPU密集型并行计算:

ForkJoinPool pool = new ForkJoinPool(); RecursiveTask<Integer> task = new MyRecursiveTask(data); Integer result = pool.invoke(task);

2.4 线程池状态

  • RUNNING:正常运行,接受新任务并处理队列任务
  • SHUTDOWN:关闭状态,不再接受新任务,继续处理队列任务
  • STOP:停止状态,不再接受新任务,不处理队列任务,中断正在执行的任务
  • TIDYING:整理状态,所有任务已终止,workerCount为0
  • TERMINATED:终止状态,terminated()方法已执行完成

2.5 线程池参数详解

核心参数
  • 核心线程数(corePoolSize):线程池保持的最小线程数
  • 最大线程数(maximumPoolSize):线程池允许的最大线程数
  • 存活时间(keepAliveTime):非核心线程空闲时的存活时间
阻塞队列类型
  • ArrayBlockingQueue:基于数组的有界阻塞队列
  • LinkedBlockingQueue:基于链表的可选有界阻塞队列
  • DelayQueue:基于优先级的延迟队列,元素按到期时间排序
拒绝策略
  • AbortPolicy:默认策略,直接抛出RejectedExecutionException异常
  • CallerRunsPolicy:由调用者线程执行被拒绝的任务
  • DiscardPolicy:直接丢弃被拒绝的任务,不抛异常
  • DiscardOldestPolicy:丢弃队列中最旧的任务,然后尝试重新提交当前任务

2.6 线程池执行流程

  1. 提交任务到线程池
  2. 如果当前线程数小于核心线程数,创建新线程执行任务
  3. 如果线程数达到核心线程数,将任务放入阻塞队列
  4. 如果队列已满且线程数小于最大线程数,创建新线程执行任务
  5. 如果队列已满且线程数达到最大线程数,执行拒绝策略

三、线程协作方式

3.1 Object类方法

必须在synchronized同步块中使用:

  • wait():使当前线程等待,释放对象锁
  • notify():随机唤醒一个等待该对象锁的线程
  • notifyAll():唤醒所有等待该对象锁的线程

3.2 Thread类方法

  • sleep(long millis):使当前线程休眠指定毫秒数,不释放锁
  • join():等待目标线程执行完毕
  • yield():提示调度器当前线程愿意让出CPU

3.3 ReentrantLock的Condition

提供更灵活的线程等待/通知机制:

ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { condition.await(); // 等待 condition.signal(); // 唤醒一个 condition.signalAll(); // 唤醒所有 } finally { lock.unlock(); }

四、锁机制

4.1 synchronized关键字

Java内置的同步锁,基于对象监视器实现:

// 同步方法 public synchronized void method() { } // 同步代码块 synchronized (obj) { // 临界区代码 }

4.2 AQS(AbstractQueuedSynchronizer)

构建锁和同步器的框架,核心实现包括:

  • ReentrantLock:可重入独占锁
  • ReentrantReadWriteLock:读写锁,支持读读并发

4.3 CAS(Compare And Swap)

无锁编程的核心技术,通过Unsafe类直接操作内存:

// 原子更新操作 AtomicInteger atomicInt = new AtomicInteger(0); atomicInt.compareAndSet(0, 1); // 比较并交换

五、并发协作工具类

5.1 CountDownLatch

计数器,等待多个线程完成:

CountDownLatch latch = new CountDownLatch(3); // 多个线程执行latch.countDown() latch.await(); // 等待计数器归零

5.2 CyclicBarrier

循环屏障,让一组线程相互等待,直到所有线程都到达屏障点:

CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("所有线程已到达屏障,开始执行后续任务"); }); // 线程执行逻辑 Runnable task = () -> { try { // 执行前置任务 System.out.println(Thread.currentThread().getName() + " 到达屏障"); barrier.await(); // 等待其他线程 // 所有线程到达后继续执行 } catch (Exception e) { e.printStackTrace(); } };
CyclicBarrier 与 CountDownLatch 对比
对比维度CountDownLatchCyclicBarrier
核心功能等待一组线程完成各自任务让一组线程相互等待,到达屏障点后继续
计数器单向递减,不可重置可循环使用,到达屏障后自动重置
重用性一次性使用,计数器归零后失效可重复使用,支持多轮屏障
等待方式主线程等待工作线程完成工作线程相互等待
典型场景启动服务等待依赖初始化完成多阶段并行计算,如多线程数据分片处理
异常处理countDown()不受异常影响await()抛出BrokenBarrierException

使用建议:

  • CountDownLatch:适用于一个或多个线程等待其他线程完成特定操作的场景,如服务启动、资源初始化等。
  • CyclicBarrier:适用于多个线程需要相互等待,然后同时开始下一阶段任务的场景,如并行计算、多阶段数据处理等。

5.2 Semaphore

信号量,控制并发访问数量:

Semaphore semaphore = new Semaphore(5); // 允许5个并发 semaphore.acquire(); // 获取许可 // 执行临界区代码 semaphore.release(); // 释放许可

六、原子操作类

  • AtomicInteger:原子整型
  • AtomicLong:原子长整型
  • AtomicStampedReference:带版本号的原子引用,解决ABA问题

七、异步编程

7.1 Future接口

表示异步计算的结果:

ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(() -> "result"); String result = future.get(); // 阻塞获取结果

7.2 CompletableFuture

更强大的异步编程工具,支持链式调用和组合操作:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(s -> s + " World") .thenAccept(System.out::println);

八、并发集合

8.1 ConcurrentHashMap

线程安全的HashMap实现:

  • 数据结构:数组 + 链表 + 红黑树
  • 锁机制:头结点锁(CAS + synchronized)
  • 分段锁优化,提高并发性能

8.2 CopyOnWriteArrayList

写时复制的线程安全List:

  • 读操作:无锁,直接读取原数组
  • 写操作:加锁(ReentrantLock),复制新数组
  • 适用场景:读多写少的并发场景

九、总结

Java多线程与并发编程是Java高级开发的核心技能。掌握线程基础、线程池机制、锁原理、并发工具类和异步编程,能够帮助开发者编写高效、安全的并发程序。在实际开发中,应根据具体场景选择合适的并发工具和策略,平衡性能与复杂度。