Java 线程状态包括以下六种:
状态 | 描述 | 触发条件 |
---|---|---|
NEW | 新建状态,尚未启动 | new Thread() |
RUNNABLE | 可运行状态(包含就绪和运行) | 调用start() 后 |
BLOCKED | 阻塞于锁,等待synchronized 锁 |
竞争锁失败 |
WAITING | 无限期等待,需手动唤醒 | 调用wait() /join() |
TIMED_WAITING | 有限期等待,自动唤醒 | 调用sleep(ms) /wait(ms) |
TERMINATED | 终止状态,线程执行完毕 | run() 方法执行结束 |
Thread
类class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running");
}
}
// 启动线程
new MyThread().start();
Runnable
接口Runnable task = () -> System.out.println("Runnable task");
new Thread(task).start();
FutureTask
+Callable
(支持返回值和异常处理)import java.util.concurrent.*;
Callable callable = () -> {
TimeUnit.SECONDS.sleep(1); // 模拟耗时操作
return 42; // 可返回结果
};
FutureTask futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
try {
Integer result = futureTask.get(); // 获取返回值
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
ThreadPoolExecutor
)ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数:线程池长期维持的最小线程数
10, // 最大线程数:允许创建的最大线程数
60L, // 空闲线程存活时间:超过核心线程数的线程空闲后存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 工作队列:存储待执行任务
Executors.defaultThreadFactory(), // 线程工厂:创建线程的工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:任务无法处理时的策略
);
常见拒绝策略:
AbortPolicy
(默认):抛出RejectedExecutionException
CallerRunsPolicy
:由调用者线程处理任务DiscardPolicy
:丢弃任务DiscardOldestPolicy
:丢弃队列中最旧的任务synchronized
关键字(隐式锁)public synchronized void instanceMethod() {
// 临界区代码(锁为this)
}
Class
对象public static synchronized void staticMethod() {
// 临界区代码(锁为Class对象)
}
private final Object lock = new Object();
public void blockLock() {
synchronized (lock) { // 显式指定锁对象
// 临界区代码
}
}
ReentrantLock
显式锁(可中断、支持公平锁)import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Lock lock = new ReentrantLock(); // 默认为非公平锁
// 可通过参数true启用公平锁:new ReentrantLock(true)
lock.lock(); // 阻塞获取锁
try {
// 临界区代码
} finally {
lock.unlock(); // 必须在finally中释放锁
}
// 可中断获取锁(支持线程中断)
try {
if (lock.tryLock(1, TimeUnit.SECONDS)) { // 带超时的尝试获取
try { /* ... */ }
} else {
// 超时处理
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
}
synchronized
vs ReentrantLock
对比特性 | synchronized |
ReentrantLock |
---|---|---|
实现机制 | JVM 内置(基于 Monitor 锁) | JDK 代码实现(基于 AQS) |
锁释放 | 自动释放(出作用域) | 必须手动调用unlock() |
公平锁 | 不支持 | 支持(构造参数fair ) |
条件变量 | 单一wait/notify |
支持多个Condition 对象 |
可中断性 | 不支持 | 支持lockInterruptibly() |
适用场景 | 简单同步场景 | 复杂逻辑(如超时、公平锁) |
CountDownLatch
(倒计时门闩)场景:主线程等待多个子线程完成任务。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int threadCount = 3;
CountDownLatch latch = new CountDownLatch(threadCount);
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
executor.execute(() -> {
try {
// 模拟任务执行
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 任务完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 计数器减1
}
});
}
latch.await(); // 阻塞当前线程,直到计数器为0
System.out.println("所有任务完成");
executor.shutdown();
}
}
CyclicBarrier
(循环屏障)场景:多个线程相互等待,全部到达屏障后再继续执行。
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo {
private static final int PARTIES = 3;
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(PARTIES, () ->
System.out.println("所有线程到达屏障,继续执行")); // 可选屏障突破回调
ExecutorService executor = Executors.newFixedThreadPool(PARTIES);
for (int i = 0; i < PARTIES; i++) {
executor.execute(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 等待屏障");
barrier.await(); // 等待其他线程
System.out.println(Thread.currentThread().getName() + " 继续执行");
} catch (Exception e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
Semaphore
(信号量)场景:控制同时访问共享资源的线程数(如限流)。
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
private static final int PERMITS = 3; // 允许同时访问的线程数
private static final Semaphore semaphore = new Semaphore(PERMITS);
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可(阻塞直到有可用许可)
System.out.println(Thread.currentThread().getName() + " 开始访问资源");
Thread.sleep(1000); // 模拟资源访问耗时
System.out.println(Thread.currentThread().getName() + " 释放资源");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
}
}).start();
}
}
}
ConcurrentHashMap
(线程安全的哈希表)import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo {
public static void main(String[] args) {
ConcurrentHashMap map = new ConcurrentHashMap<>();
map.put("a", 1); // 线程安全的put操作
map.putIfAbsent("b", 2); // 仅当键不存在时插入
// 原子更新操作:计算值(若不存在则初始化)
map.compute("c", (k, v) -> v != null ? v + 1 : 1);
map.computeIfAbsent("d", k -> 0); // 等价于putIfAbsent
// 线程安全的遍历
map.forEach((k, v) -> System.out.println(k + ": " + v));
}
}
CopyOnWriteArrayList
(写时复制列表)特点:迭代时不抛出ConcurrentModificationException
,适用于读多写少场景。
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListDemo {
public static void main(String[] args) {
CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();
list.add("item1");
list.add("item2");
// 安全的迭代(基于快照机制)
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
if ("item1".equals(item)) {
list.add("item3"); // 写操作会创建新数组,不影响当前迭代
}
}
}
}
BlockingQueue
(阻塞队列)场景:线程间安全通信(生产者 - 消费者模型)。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class BlockingQueueDemo {
private static final BlockingQueue queue = new LinkedBlockingQueue<>(10); // 有界队列
// 生产者线程
static class Producer implements Runnable {
@Override
public void run() {
try {
for (int i = 0; i < 5; i++) {
String data = "Data-" + i;
queue.put(data); // 队列满时阻塞
System.out.println("生产:" + data);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// 消费者线程
static class Consumer implements Runnable {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
String data = queue.take(); // 队列为空时阻塞
System.out.println("消费:" + data);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
}
AtomicInteger
(原子整数)import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerDemo {
private static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.incrementAndGet(); // 原子自增(等价于++i)
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.getAndIncrement(); // 原子自增(等价于i++)
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("最终值:" + counter.get()); // 输出:2000
}
}
LongAdder
(高并发累加器)原理:分段锁优化,将数值拆分到多个变量,减少 CAS 竞争。
import java.util.concurrent.atomic.LongAdder;
public class LongAdderDemo {
private static LongAdder adder = new LongAdder();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 10000; j++) {
adder.add(1); // 累加操作
}
}).start();
}
Thread.sleep(1000); // 等待所有线程完成
System.out.println("总和:" + adder.sum()); // 输出:100000
}
}
核心思想:通过硬件指令实现无锁原子操作,仅当值等于预期值时更新。
// 模拟CAS操作(非线程安全,仅演示逻辑)
public class SimulatedCAS {
private int value;
// 模拟CAS更新(需配合volatile保证可见性)
public int compareAndSwap(int expected, int newValue) {
int oldValue = value; // 读取当前值
if (oldValue == expected) { // 比较预期值
value = newValue; // 执行更新
}
return oldValue; // 返回旧值
}
}
volatile
volatile
关键字作用:
示例:线程安全的标志位
public class VolatileDemo {
private volatile boolean running = true; // 保证可见性
// 生产者线程:修改标志位
public void stop() {
running = false; // 写操作,强制刷新主内存
}
// 消费者线程:读取标志位
public void process() {
while (running) { // 读操作,强制从主内存获取
// 执行任务
}
}
}
jps
:查看 Java 进程 PID。jstack
:打印线程堆栈信息,定位死锁。jcmd Thread.print
:生成线程转储文件(JDK 7+)。Found one Java-level deadlock:
=============================
"Thread-0":
waiting to lock monitor 0x0000... (object x),
which is held by "Thread-1"
"Thread-1":
waiting to lock monitor 0