Java多线程机制与并发控制
一、线程基础概念
线程是程序执行的最小单位,代表一个独立的运行路径。多个线程之间可通过协作、互斥和同步机制进行交互。
线程创建方式
- 继承
Thread类并重写run()方法 - 实现
Runnable接口,将任务逻辑封装在run()中 - 使用匿名内部类或 Lambda 表达式创建可执行任务
- 通过
Callable接口支持带返回值的任务,且可抛出受检异常
常用线程操作方法
// 启动线程
void start();
// 线程休眠(毫秒级)
static void sleep(long millis);
// 带纳秒精度的休眠
static void sleep(long millis, int nanos);
// 等待当前线程终止
void join();
// 释放处理器资源,让出执行权
static void yield();
// 获取当前正在执行的线程引用
static Thread currentThread();
二、线程生命周期与状态流转
线程在运行过程中会经历以下状态转换:
- 新建(New):线程对象被创建但尚未启动。
- 就绪(Runnable):调用
start()后进入此状态,等待系统调度获取 CPU 时间片。 - 运行(Running):已获得 CPU 执行权,正在执行代码。
- 阻塞(Blocked):
- 等待阻塞:调用
Object.wait()被放入等待队列。 - 同步阻塞:尝试获取锁失败,进入锁池等待。
- 其他阻塞:如调用
sleep()、join()或执行 I/O 操作。
- 等待阻塞:调用
- 终止(Terminated):
run()方法执行完毕或异常退出,无法再次启动。
三、关键注意点
Thread.sleep()是静态方法,作用于当前线程,而非指定线程对象。- 休眠期间不会释放锁,与其他线程竞争时需重新获取调度权。
- 若被中断,
sleep()会抛出InterruptedException。 - 唤醒后仅进入就绪状态,不保证立即执行。
SimpleDateFormat不是线程安全的,应避免在多线程中共享实例。
四、并发控制工具类
JDK 提供了多种同步辅助工具,用于协调线程行为:
- CountDownLatch:允许一组线程等待某个事件发生,常用于初始化完成或任务结束通知。
- CyclicBarrier:使多个线程在特定点汇合,适用于分阶段任务处理。
- Semaphore:控制同时访问资源的线程数量,实现资源池管理。
- Exchanger:两个线程交换数据,常用于生产者-消费者模式。
五、ThreadLocal 的原理与应用
ThreadLocal 为每个线程维护一份独立的数据副本,实现线程本地存储。
- 内部使用
ThreadLocalMap存储键值对,其中Entry为弱引用,防止内存泄漏。 - 每个线程访问的是自己私有的变量拷贝,确保数据隔离,适合用于保存用户上下文、事务标识等场景。
- 典型结构如下:
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal> {
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
}