一、JUC(java.util.concurrent)核心类详解
1.1 Callable 与 FutureTask
Callable基础使用
java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableDemo {
/**
* Callable与Runnable对比:
* - Runnable的run()方法没有返回值
* - Callable的call()方法有返回值,支持泛型,可以抛出异常
*/
public static void basicCallableUsage() throws ExecutionException, InterruptedException {
// 创建Callable任务
Callable<Integer> callable = new Callable<Integer>() {
@Override
` public Integer call() throws Exception {
System.out.println("Callable任务开始执行...");
Thread.sleep(2000); // 模拟耗时操作
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum; // 返回计算结果
}
};
// 使用FutureTask包装Callable
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 创建线程并执行
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("主线程继续执行其他任务...");
// 获取任务结果(会阻塞直到任务完成)
Integer result = futureTask.get();
System.out.println("计算结果: " + result); // 输出: 5050
}
/**
* 带异常处理的Callable
*/
public static void callableWithException() {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
if (Math.random() > 0.5) {
throw new RuntimeException("随机异常发生!");
}
return "任务成功完成";
}
};
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
try {
String result = futureTask.get();
System.out.println("结果: " + result);
} catch (InterruptedException | ExecutionException e) {
System.err.println("任务执行异常: " + e.getCause().getMessage());
}
}
/**
* 多个Callable任务并行执行
*/
public static void multipleCallableTasks() throws InterruptedException, ExecutionException {
Callable<Long> factorialTask = new Callable<Long>() {
@Override
public Long call() throws Exception {
long result = 1;
for (int i = 1; i <= 10; i++) {
result *= i;
Thread.sleep(100);
}
return result;
}
};
Callable<Long> sumTask = new Callable<Long>() {
@Override
public Long call() throws Exception {
long result = 0;
for (int i = 1; i <= 100; i++) {
result += i;
Thread.sleep(10);
}
return result;
}
};
FutureTask<Long> factorialFuture = new FutureTask<>(factorialTask);
FutureTask<Long> sumFuture = new FutureTask<>(sumTask);
Thread t1 = new Thread(factorialFuture);
Thread t2 = new Thread(sumFuture);
long startTime = System.currentTimeMillis();
t1.start();
t2.start();
// 并行执行,总时间约等于最慢的任务
Long factorialResult = factorialFuture.get();
Long sumResult = sumFuture.get();
long endTime = System.currentTimeMillis();
System.out.println("阶乘结果: " + factorialResult); // 3628800
System.out.println("累加结果: " + sumResult); // 5050
System.out.println("总耗时: " + (endTime - startTime) + "ms");
}
public static void main(String[] args) throws Exception {
System.out.println("=== Callable基础使用 ===");
basicCallableUsage();
System.out.println("\n=== 带异常的Callable ===");
callableWithException();
System.out.println("\n=== 多个Callable任务 ===");
multipleCallableTasks();
}
}
Lambda表达式简化Callable
java
import java.util.concurrent.*;
public class CallableLambda {
public static void main(String[] args) throws Exception {
// 使用Lambda表达式简化Callable创建
Callable<String> callable = () -> {
Thread.sleep(1000);
return "Hello from Callable: " + Thread.currentThread().getName();
};
FutureTask<String> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
System.out.println("主线程做其他事情...");
String result = futureTask.get();
System.out.println(result);
// 更简洁的写法
FutureTask<Integer> simpleTask = new FutureTask<>(() -> {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
return sum;
});
new Thread(simpleTask).start();
System.out.println("简单任务结果: " + simpleTask.get());
}
}
1.2 ReentrantLock 深度解析
ReentrantLock 基础使用
java
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class ReentrantLockDemo {
private final ReentrantLock lock = new ReentrantLock();
private int counter = 0;
/**
* 基础锁操作
*/
public void basicLockOperation() {
lock.lock(); // 获取锁
try {
counter++;
System.out.println(Thread.currentThread().getName() + " - Counter: " + counter);
} finally {
lock.unlock(); // 必须在finally中释放锁
}
}
/**
* tryLock() 非阻塞获取锁
*/
public void tryLockDemo() {
if (lock.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " 成功获取锁");
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " 获取锁失败,执行其他操作");
}
}
/**
* 带超时的tryLock
*/
public void tryLockWithTimeout() {
try {
if (lock.tryLock(1, java.util.concurrent.TimeUnit.SECONDS)) {
try {
System.out.println(Thread.currentThread().getName() + " 在超时时间内获取到锁");
Thread.sleep(500);
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " 获取锁超时");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 公平锁 vs 非公平锁
*/
public static void fairVsUnfair() throws InterruptedException {
System.out.println("=== 非公平锁测试 ===");
testLock(false);
Thread.sleep(1000);
System.out.println("=== 公平锁测试 ===");
testLock(true);
}
private static void testLock(boolean fair) throws InterruptedException {
ReentrantLock lock = new ReentrantLock(fair);
int threadCount = 5;
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
lock.lock();
try {
System.out.println("线程" + threadId + "获取到锁");
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}).start();
// 稍微错开启动时间
Thread.sleep(10);
}
}
/**
* Condition 条件变量 - 生产者消费者模式
*/
public static void conditionDemo() {
ReentrantLock lock = new ReentrantLock();
Condition notFull = lock.newCondition(); // 队列未满条件
Condition notEmpty = lock.newCondition(); // 队列非空条件
final int capacity = 5;
int[] queue = new int[capacity];
int count = 0, putIndex = 0, takeIndex = 0;
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (count == capacity) {
System.out.println("队列已满,生产者等待...");
notFull.await();
}
queue[putIndex] = i;
putIndex = (putIndex + 1) % capacity;
count++;
System.out.println("生产: " + i);
notEmpty.signal(); // 唤醒消费者
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (count == 0) {
System.out.println("队列为空,消费者等待...");
notEmpty.await();
}
int value = queue[takeIndex];
takeIndex = (takeIndex + 1) % capacity;
count--;
System.out.println("消费: " + value);
notFull.signal(); // 唤醒生产者
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
try {
Thread.sleep(150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
}
public static void main(String[] args) throws Exception {
ReentrantLockDemo demo = new ReentrantLockDemo();
// 测试基础锁操作
System.out.println("=== 基础锁操作测试 ===");
for (int i = 0; i < 5; i++) {
new Thread(demo::basicLockOperation).start();
}
Thread.sleep(1000);
// 测试tryLock
System.out.println("\n=== tryLock测试 ===");
for (int i = 0; i < 3; i++) {
new Thread(demo::tryLockDemo).start();
}
Thread.sleep(1000);
// 测试公平锁
fairVsUnfair();
// 测试Condition
System.out.println("\n=== Condition测试 ===");
conditionDemo();
}
}
ReentrantLock 与 synchronized 对比
java
public class LockComparison {
private final Object syncLock = new Object();
private final ReentrantLock reentrantLock = new ReentrantLock();
private int syncCounter = 0;
private int lockCounter = 0;
/**
* synchronized 方式
*/
public void incrementSync() {
synchronized(syncLock) {
syncCounter++;
System.out.println("synchronized: " + syncCounter);
}
}
/**
* ReentrantLock 方式
*/
public void incrementLock() {
reentrantLock.lock();
try {
lockCounter++;
System.out.println("ReentrantLock: " + lockCounter);
} finally {
reentrantLock.unlock();
}
}
/**
* 性能对比测试
*/
public void performanceTest() throws InterruptedException {
int threadCount = 10;
int iterations = 10000;
// 测试synchronized性能
long syncStart = System.currentTimeMillis();
Thread[] syncThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
syncThreads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
incrementSync();
}
});
syncThreads[i].start();
}
for (Thread t : syncThreads) t.join();
long syncEnd = System.currentTimeMillis();
// 测试ReentrantLock性能
long lockStart = System.currentTimeMillis();
Thread[] lockThreads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
lockThreads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
incrementLock();
}
});
lockThreads[i].start();
}
for (Thread t : lockThreads) t.join();
long lockEnd = System.currentTimeMillis();
System.out.println("synchronized 耗时: " + (syncEnd - syncStart) + "ms");
System.out.println("ReentrantLock 耗时: " + (lockEnd - lockStart) + "ms");
}
public static void main(String[] args) throws Exception {
LockComparison comparison = new LockComparison();
comparison.performanceTest();
}
}
1.3 线程池深度使用
各种线程池的创建和使用
java
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolDetailed {
/**
* 1. 固定大小线程池
*/
public static void fixedThreadPoolDemo() throws InterruptedException {
System.out.println("=== 固定大小线程池 ===");
ExecutorService fixedPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int taskId = i;
fixedPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
fixedPool.shutdown();
fixedPool.awaitTermination(10, TimeUnit.SECONDS);
}
/**
* 2. 单线程线程池
*/
public static void singleThreadPoolDemo() {
System.out.println("\n=== 单线程线程池 ===");
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int taskId = i;
singleThreadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
});
}
singleThreadPool.shutdown();
}
/**
* 3. 可缓存线程池
*/
public static void cachedThreadPoolDemo() throws InterruptedException {
System.out.println("\n=== 可缓存线程池 ===");
ExecutorService cachedPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int taskId = i;
cachedPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread.sleep(100); // 控制任务提交速度
}
cachedPool.shutdown();
cachedPool.awaitTermination(5, TimeUnit.SECONDS);
}
/**
* 4. 定时线程池
*/
public static void scheduledThreadPoolDemo() throws InterruptedException {
System.out.println("\n=== 定时线程池 ===");
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
// 延迟执行
scheduledPool.schedule(() -> {
System.out.println("延迟3秒执行的任务");
}, 3, TimeUnit.SECONDS);
// 固定频率执行
scheduledPool.scheduleAtFixedRate(() -> {
System.out.println("固定频率任务执行: " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);
// 固定延迟执行
scheduledPool.scheduleWithFixedDelay(() -> {
System.out.println("固定延迟任务执行: " + System.currentTimeMillis());
try {
Thread.sleep(1000); // 模拟任务执行时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, 1, 2, TimeUnit.SECONDS);
Thread.sleep(10000);
scheduledPool.shutdown();
}
/**
* 5. 自定义线程池
*/
public static void customThreadPoolDemo() throws InterruptedException {
System.out.println("\n=== 自定义线程池 ===");
ThreadPoolExecutor customPool = new ThreadPoolExecutor(
2, // 核心线程数
5, // 最大线程数
60, // 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(10), // 任务队列
new CustomThreadFactory(), // 线程工厂
new CustomRejectionPolicy() // 拒绝策略
);
// 监控线程
Thread monitor = new Thread(() -> {
while (!customPool.isTerminated()) {
System.out.printf("监控: 池大小=%d, 活跃线程=%d, 队列大小=%d, 完成任务=%d%n",
customPool.getPoolSize(),
customPool.getActiveCount(),
customPool.getQueue().size(),
customPool.getCompletedTaskCount());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
monitor.setDaemon(true);
monitor.start();
// 提交任务
for (int i = 0; i < 20; i++) {
final int taskId = i;
try {
customPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
} catch (RejectedExecutionException e) {
System.out.println("任务 " + taskId + " 被拒绝");
}
Thread.sleep(100);
}
customPool.shutdown();
customPool.awaitTermination(30, TimeUnit.SECONDS);
}
/**
* 自定义线程工厂
*/
static class CustomThreadFactory implements ThreadFactory {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "CustomPool-Thread-" + threadNumber.getAndIncrement());
thread.setDaemon(false);
thread.setPriority(Thread.NORM_PRIORITY);
return thread;
}
}
/**
* 自定义拒绝策略
*/
static class CustomRejectionPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.err.println("任务被拒绝,执行拒绝策略");
if (!executor.isShutdown()) {
// 尝试重新放入队列
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("重新放入队列失败");
}
}
}
}
public static void main(String[] args) throws Exception {
fixedThreadPoolDemo();
singleThreadPoolDemo();
cachedThreadPoolDemo();
scheduledThreadPoolDemo();
customThreadPoolDemo();
}
}
1.4 信号量 (Semaphore)
Semaphore 详细使用
java
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDetailed {
/**
* 基础信号量使用 - 资源池模拟
*/
public static void basicSemaphore() throws InterruptedException {
System.out.println("=== 基础信号量 - 数据库连接池模拟 ===");
// 模拟3个数据库连接
Semaphore connectionPool = new Semaphore(3);
// 创建10个需要数据库连接的线程
for (int i = 0; i < 10; i++) {
final int threadId = i;
new Thread(() -> {
try {
System.out.println("线程 " + threadId + " 等待数据库连接...");
connectionPool.acquire(); // 获取许可
System.out.println("线程 " + threadId + " 获取到数据库连接,开始操作...");
// 模拟数据库操作
Thread.sleep(2000);
System.out.println("线程 " + threadId + " 释放数据库连接");
connectionPool.release(); // 释放许可
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
Thread.sleep(300); // 控制线程启动间隔
}
Thread.sleep(10000);
}
/**
* 带超时的信号量获取
*/
public static void semaphoreWithTimeout() throws InterruptedException {
System.out.println("\n=== 带超时的信号量 ===");
Semaphore semaphore = new Semaphore(2);
for (int i = 0; i < 5; i++) {
final int threadId = i;
new Thread(() -> {
try {
System.out.println("线程 " + threadId + " 尝试获取信号量...");
// 尝试在1秒内获取信号量
if (semaphore.tryAcquire(1, TimeUnit.SECONDS)) {
try {
System.out.println("线程 " + threadId + " 成功获取信号量");
Thread.sleep(1500); // 模拟工作
} finally {
semaphore.release();
System.out.println("线程 " + threadId + " 释放信号量");
}
} else {
System.out.println("线程 " + threadId + " 获取信号量超时");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
Thread.sleep(8000);
}
/**
* 多资源类型的信号量
*/
public static void multipleResourceSemaphore() throws InterruptedException {
System.out.println("\n=== 多资源类型信号量 ===");
// 模拟两种资源:CPU核心和内存块
Semaphore cpuCores = new Semaphore(2); // 2个CPU核心
Semaphore memoryBlocks = new Semaphore(3); // 3个内存块
for (int i = 0; i < 6; i++) {
final int taskId = i;
new Thread(() -> {
try {
System.out.println("任务 " + taskId + " 申请资源...");
// 同时申请两种资源
cpuCores.acquire();
memoryBlocks.acquire();
System.out.println("任务 " + taskId + " 获得所有资源,开始执行...");
Thread.sleep(1000); // 模拟任务执行
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
memoryBlocks.release();
cpuCores.release();
System.out.println("任务 " + taskId + " 释放所有资源");
}
}).start();
}
Thread.sleep(8000);
}
/**
* 信号量实现生产者消费者
*/
public static void semaphoreProducerConsumer() throws InterruptedException {
System.out.println("\n=== 信号量实现生产者消费者 ===");
final int bufferSize = 5;
int[] buffer = new int[bufferSize];
int in = 0, out = 0;
Semaphore mutex = new Semaphore(1); // 互斥信号量
Semaphore empty = new Semaphore(bufferSize); // 空槽位信号量
Semaphore full = new Semaphore(0); // 满槽位信号量
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
empty.acquire(); // 等待空槽位
mutex.acquire(); // 获取互斥锁
// 生产数据
buffer[in] = i;
System.out.println("生产: " + i + " 到位置 " + in);
in = (in + 1) % bufferSize;
mutex.release(); // 释放互斥锁
full.release(); // 增加满槽位
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
full.acquire(); // 等待满槽位
mutex.acquire(); // 获取互斥锁
// 消费数据
int value = buffer[out];
System.out.println("消费: " + value + " 从位置 " + out);
out = (out + 1) % bufferSize;
mutex.release(); // 释放互斥锁
empty.release(); // 增加空槽位
Thread.sleep(150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
public static void main(String[] args) throws Exception {
basicSemaphore();
semaphoreWithTimeout();
multipleResourceSemaphore();
semaphoreProducerConsumer();
}
}
1.5 CountDownLatch 详细使用
CountDownLatch 应用场景
java
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
public class CountDownLatchDetailed {
/**
* 场景1:多任务并行执行,主线程等待所有任务完成
*/
public static void parallelTasks() throws InterruptedException {
System.out.println("=== 并行任务执行 ===");
int taskCount = 5;
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
final int taskId = i;
new Thread(() -> {
try {
// 模拟任务执行时间
int sleepTime = ThreadLocalRandom.current().nextInt(1000, 3000);
Thread.sleep(sleepTime);
System.out.println("任务 " + taskId + " 完成,耗时 " + sleepTime + "ms");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown(); // 任务完成,计数器减1
}
}).start();
}
System.out.println("主线程等待所有任务完成...");
latch.await(); // 阻塞直到计数器为0
System.out.println("所有任务已完成,主线程继续执行");
}
/**
* 场景2:比赛开始信号
*/
public static void raceStart() throws InterruptedException {
System.out.println("\n=== 比赛开始信号 ===");
int runnerCount = 4;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch finishSignal = new CountDownLatch(runnerCount);
// 运动员线程
for (int i = 0; i < runnerCount; i++) {
final int runnerId = i;
new Thread(() -> {
try {
System.out.println("运动员 " + runnerId + " 准备就绪,等待发令枪...");
startSignal.await(); // 等待发令枪响
// 开始跑步
System.out.println("运动员 " + runnerId + " 起跑!");
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
System.out.println("运动员 " + runnerId + " 到达终点");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
finishSignal.countDown();
}
}).start();
}
// 裁判线程
Thread.sleep(2000); // 裁判准备时间
System.out.println("预备...砰!");
startSignal.countDown(); // 发令枪响
finishSignal.await(); // 等待所有运动员到达终点
System.out.println("比赛结束!");
}
/**
* 场景3:多阶段任务
*/
public static void multiPhaseTasks() throws InterruptedException {
System.out.println("\n=== 多阶段任务 ===");
int phase1Tasks = 3;
int phase2Tasks = 2;
CountDownLatch phase1Latch = new CountDownLatch(phase1Tasks);
CountDownLatch phase2Latch = new CountDownLatch(phase2Tasks);
// 第一阶段任务
for (int i = 0; i < phase1Tasks; i++) {
final int taskId = i;
new Thread(() -> {
try {
System.out.println("第一阶段任务 " + taskId + " 开始");
Thread.sleep(1000 + taskId * 500);
System.out.println("第一阶段任务 " + taskId + " 完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
phase1Latch.countDown();
}
}).start();
}
// 等待第一阶段完成
phase1Latch.await();
System.out.println("=== 第一阶段所有任务完成,开始第二阶段 ===");
// 第二阶段任务
for (int i = 0; i < phase2Tasks; i++) {
final int taskId = i;
new Thread(() -> {
try {
System.out.println("第二阶段任务 " + taskId + " 开始");
Thread.sleep(1500 + taskId * 500);
System.out.println("第二阶段任务 " + taskId + " 完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
phase2Latch.countDown();
}
}).start();
}
// 等待第二阶段完成
phase2Latch.await();
System.out.println("=== 所有阶段任务完成 ===");
}
/**
* 场景4:带超时的等待
*/
public static void timeoutWait() throws InterruptedException {
System.out.println("\n=== 带超时的等待 ===");
CountDownLatch latch = new CountDownLatch(3);
// 两个正常完成的任务
for (int i = 0; i < 2; i++) {
final int taskId = i;
new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("任务 " + taskId + " 正常完成");
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
// 一个超时任务
new Thread(() -> {
try {
Thread.sleep(5000); // 这个任务会超时
System.out.println("超时任务完成");
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// 主线程最多等待3秒
boolean completed = latch.await(3, TimeUnit.SECONDS);
if (completed) {
System.out.println("所有任务在超时前完成");
} else {
System.out.println("等待超时,还有 " + latch.getCount() + " 个任务未完成");
}
}
public static void main(String[] args) throws Exception {
parallelTasks();
raceStart();
multiPhaseTasks();
timeoutWait();
}
}
二、线程安全的集合类
2.1 多线程环境下的 List
各种线程安全List对比
java
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
public class ThreadSafeListDemo {
/**
* 1. 手动加锁的ArrayList
*/
public static void manualSynchronizedArrayList() throws InterruptedException {
System.out.println("=== 手动加锁的ArrayList ===");
List<Integer> list = new ArrayList<>();
Object lock = new Object();
int threadCount = 10;
int operationsPerThread = 1000;
CountDownLatch latch = new CountDownLatch(threadCount);
long startTime = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
synchronized(lock) {
list.add(threadId * operationsPerThread + j);
}
}
latch.countDown();
}).start();
}
latch.await();
long endTime = System.currentTimeMillis();
System.out.println("手动加锁ArrayList大小: " + list.size());
System.out.println("耗时: " + (endTime - startTime) + "ms");
}
/**
* 2. Collections.synchronizedList
*/
public static void synchronizedListWrapper() throws InterruptedException {
System.out.println("\n=== Collections.synchronizedList ===");
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
int threadCount = 10;
int operationsPerThread = 1000;
CountDownLatch latch = new CountDownLatch(threadCount);
long startTime = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
list.add(threadId * operationsPerThread + j);
}
latch.countDown();
}).start();
}
latch.await();
long endTime = System.currentTimeMillis();
System.out.println("synchronizedList大小: " + list.size());
System.out.println("耗时: " + (endTime - startTime) + "ms");
}
/**
* 3. CopyOnWriteArrayList
*/
public static void copyOnWriteArrayListDemo() throws InterruptedException {
System.out.println("\n=== CopyOnWriteArrayList ===");
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
int threadCount = 10;
int operationsPerThread = 1000;
CountDownLatch latch = new CountDownLatch(threadCount);
long startTime = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
list.add(threadId * operationsPerThread + j);
}
latch.countDown();
}).start();
}
latch.await();
long endTime = System.currentTimeMillis();
System.out.println("CopyOnWriteArrayList大小: " + list.size());
System.out.println("耗时: " + (endTime - startTime) + "ms");
}
/**
* CopyOnWriteArrayList 适用场景演示
*/
public static void copyOnWriteSuitableScenario() throws InterruptedException {
System.out.println("\n=== CopyOnWriteArrayList 适用场景 ===");
CopyOnWriteArrayList<String> configList = new CopyOnWriteArrayList<>();
// 初始化配置
configList.add("server.port=8080");
configList.add("database.url=jdbc:mysql://localhost:3306/test");
configList.add("cache.enabled=true");
// 多个读取线程
for (int i = 0; i < 5; i++) {
new Thread(() -> {
while (true) {
// 读取操作很快,不需要加锁
for (String config : configList) {
// 模拟读取配置
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}).start();
}
// 配置更新线程(很少发生)
Thread configUpdater = new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("开始更新配置...");
// 创建新的配置列表
CopyOnWriteArrayList<String> newConfig = new CopyOnWriteArrayList<>();
newConfig.add("server.port=8081"); // 修改端口
newConfig.add("database.url=jdbc:mysql://localhost:3306/prod"); // 修改数据库
newConfig.add("cache.enabled=false"); // 修改缓存设置
newConfig.add("new.feature=true"); // 新增配置
// 替换整个配置列表
configList.clear();
configList.addAll(newConfig);
System.out.println("配置更新完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
configUpdater.start();
configUpdater.join();
System.out.println("最终配置: " + configList);
}
/**
* 性能对比测试
*/
public static void performanceComparison() throws InterruptedException {
System.out.println("\n=== 性能对比测试 ===");
int threadCount = 20;
int operationsPerThread = 1000;
// 测试手动加锁ArrayList
List<Integer> manualList = new ArrayList<>();
Object lock = new Object();
CountDownLatch latch1 = new CountDownLatch(threadCount);
long start1 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
synchronized(lock) {
manualList.add(j);
}
}
latch1.countDown();
}).start();
}
latch1.await();
long end1 = System.currentTimeMillis();
// 测试synchronizedList
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
CountDownLatch latch2 = new CountDownLatch(threadCount);
long start2 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
syncList.add(j);
}
latch2.countDown();
}).start();
}
latch2.await();
long end2 = System.currentTimeMillis();
// 测试CopyOnWriteArrayList
CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<>();
CountDownLatch latch3 = new CountDownLatch(threadCount);
long start3 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
cowList.add(j);
}
latch3.countDown();
}).start();
}
latch3.await();
long end3 = System.currentTimeMillis();
System.out.println("手动加锁ArrayList: " + (end1 - start1) + "ms");
System.out.println("synchronizedList: " + (end2 - start2) + "ms");
System.out.println("CopyOnWriteArrayList: " + (end3 - start3) + "ms");
}
public static void main(String[] args) throws Exception {
manualSynchronizedArrayList();
synchronizedListWrapper();
copyOnWriteArrayListDemo();
copyOnWriteSuitableScenario();
performanceComparison();
}
}
2.2 多线程环境下的队列
各种阻塞队列对比
java
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadSafeQueueDemo {
/**
* 1. ArrayBlockingQueue - 有界阻塞队列
*/
public static void arrayBlockingQueueDemo() throws InterruptedException {
System.out.println("=== ArrayBlockingQueue ===");
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
// 生产者
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
queue.put(i); // 如果队列满则阻塞
System.out.println("生产: " + i + " 队列大小: " + queue.size());
Thread.sleep(100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 消费者
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
Integer value = queue.take(); // 如果队列空则阻塞
System.out.println("消费: " + value + " 队列大小: " + queue.size());
Thread.sleep(200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
/**
* 2. LinkedBlockingQueue - 可选的边界阻塞队列
*/
public static void linkedBlockingQueueDemo() throws InterruptedException {
System.out.println("\n=== LinkedBlockingQueue ===");
// 无界队列
LinkedBlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();
// 有界队列
LinkedBlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(3);
// 测试有界队列的生产者消费者
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 6; i++) {
boolean success = boundedQueue.offer(i, 1, TimeUnit.SECONDS);
if (success) {
System.out.println("生产: " + i + " 成功");
} else {
System.out.println("生产: " + i + " 超时");
}
Thread.sleep(300);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 6; i++) {
Integer value = boundedQueue.poll(2, TimeUnit.SECONDS);
if (value != null) {
System.out.println("消费: " + value + " 成功");
} else {
System.out.println("消费超时");
}
Thread.sleep(500);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
/**
* 3. PriorityBlockingQueue - 带优先级的阻塞队列
*/
public static void priorityBlockingQueueDemo() throws InterruptedException {
System.out.println("\n=== PriorityBlockingQueue ===");
PriorityBlockingQueue<Integer> priorityQueue = new PriorityBlockingQueue<>();
// 生产者 - 插入无序数据
Thread producer = new Thread(() -> {
int[] data = {5, 1, 8, 3, 9, 2};
for (int value : data) {
priorityQueue.put(value);
System.out.println("插入: " + value);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者 - 按优先级取出
Thread consumer = new Thread(() -> {
for (int i = 0; i < 6; i++) {
try {
Integer value = priorityQueue.take();
System.out.println("取出: " + value + " (队列大小: " + priorityQueue.size() + ")");
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
/**
* 4. SynchronousQueue - 不存储元素的阻塞队列
*/
public static void synchronousQueueDemo() throws InterruptedException {
System.out.println("\n=== SynchronousQueue ===");
SynchronousQueue<Integer> syncQueue = new SynchronousQueue<>(true); // 公平模式
AtomicInteger produced = new AtomicInteger(0);
AtomicInteger consumed = new AtomicInteger(0);
// 生产者
Thread producer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
System.out.println("生产者尝试传递: " + i);
syncQueue.put(i);
produced.incrementAndGet();
System.out.println("生产者成功传递: " + i);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者
Thread consumer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
System.out.println("消费者等待接收...");
Integer value = syncQueue.take();
consumed.incrementAndGet();
System.out.println("消费者接收到: " + value);
Thread.sleep(1000); // 模拟处理时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
System.out.println("生产数量: " + produced.get() + ", 消费数量: " + consumed.get());
}
/**
* 5. 延迟队列 DelayQueue
*/
public static void delayQueueDemo() throws InterruptedException {
System.out.println("\n=== DelayQueue ===");
DelayQueue<DelayedTask> delayQueue = new DelayQueue<>();
// 添加延迟任务
long now = System.currentTimeMillis();
delayQueue.put(new DelayedTask("任务1", now + 3000)); // 3秒后执行
delayQueue.put(new DelayedTask("任务2", now + 1000)); // 1秒后执行
delayQueue.put(new DelayedTask("任务3", now + 5000)); // 5秒后执行
System.out.println("开始等待延迟任务...");
while (!delayQueue.isEmpty()) {
DelayedTask task = delayQueue.take();
System.out.println("执行: " + task);
}
System.out.println("所有延迟任务执行完成");
}
static class DelayedTask implements Delayed {
private final String name;
private final long executeTime;
public DelayedTask(String name, long executeTime) {
this.name = name;
this.executeTime = executeTime;
}
@Override
public long getDelay(TimeUnit unit) {
long diff = executeTime - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
if (this.executeTime < ((DelayedTask) other).executeTime) {
return -1;
}
if (this.executeTime > ((DelayedTask) other).executeTime) {
return 1;
}
return 0;
}
@Override
public String toString() {
return "DelayedTask{" + "name='" + name + ''' +
", executeTime=" + executeTime + '}';
}
}
public static void main(String[] args) throws Exception {
arrayBlockingQueueDemo();
linkedBlockingQueueDemo();
priorityBlockingQueueDemo();
synchronousQueueDemo();
delayQueueDemo();
}
}
2.3 多线程环境下的哈希表
ConcurrentHashMap 深度解析
java
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ConcurrentHashMapDemo {
/**
* ConcurrentHashMap 基础操作
*/
public static void basicOperations() {
System.out.println("=== ConcurrentHashMap 基础操作 ===");
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 并发安全的put操作
map.put("key1", 1);
map.put("key2", 2);
map.put("key3", 3);
// 如果不存在则添加
map.putIfAbsent("key1", 100); // 不会替换,因为key1已存在
map.putIfAbsent("key4", 4); // 会添加,因为key4不存在
// 原子操作
map.compute("key1", (k, v) -> v == null ? 1 : v + 1); // key1的值+1
map.merge("key2", 10, (oldVal, newVal) -> oldVal + newVal); // 合并
System.out.println("Map内容: " + map);
}
/**
* 并发性能测试
*/
public static void performanceTest() throws InterruptedException {
System.out.println("\n=== 并发性能测试 ===");
int threadCount = 10;
int operationsPerThread = 10000;
// 测试ConcurrentHashMap
ConcurrentHashMap<Integer, String> concurrentMap = new ConcurrentHashMap<>();
CountDownLatch latch1 = new CountDownLatch(threadCount);
long start1 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
concurrentMap.put(threadId * operationsPerThread + j, "value");
}
latch1.countDown();
}).start();
}
latch1.await();
long end1 = System.currentTimeMillis();
// 测试Hashtable
Hashtable<Integer, String> hashtable = new Hashtable<>();
CountDownLatch latch2 = new CountDownLatch(threadCount);
long start2 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
hashtable.put(threadId * operationsPerThread + j, "value");
}
latch2.countDown();
}).start();
}
latch2.await();
long end2 = System.currentTimeMillis();
// 测试Collections.synchronizedMap
Map<Integer, String> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
CountDownLatch latch3 = new CountDownLatch(threadCount);
long start3 = System.currentTimeMillis();
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
synchronizedMap.put(threadId * operationsPerThread + j, "value");
}
latch3.countDown();
}).start();
}
latch3.await();
long end3 = System.currentTimeMillis();
System.out.println("ConcurrentHashMap 耗时: " + (end1 - start1) + "ms");
System.out.println("Hashtable 耗时: " + (end2 - start2) + "ms");
System.out.println("synchronizedMap 耗时: " + (end3 - start3) + "ms");
}
/**
* ConcurrentHashMap 高级特性
*/
public static void advancedFeatures() {
System.out.println("\n=== ConcurrentHashMap 高级特性 ===");
ConcurrentHashMap<String, AtomicInteger> wordCountMap = new ConcurrentHashMap<>();
// 模拟文本处理
String[] documents = {
"hello world java concurrent",
"java programming is fun",
"concurrent programming in java",
"hello java world"
};
// 并行处理文档
Arrays.stream(documents)
.parallel()
.forEach(document -> {
String[] words = document.split(" ");
for (String word : words) {
// 原子更新
wordCountMap.compute(word, (k, v) -> {
if (v == null) {
return new AtomicInteger(1);
} else {
v.incrementAndGet();
return v;
}
});
}
});
System.out.println("词频统计: " + wordCountMap);
// 搜索操作
long count = wordCountMap.search(2, (key, value) ->
value.get() > 2 ? key : null
);
System.out.println("出现超过2次的单词: " + (count != null ? count : "无"));
// 归约操作
int totalWords = wordCountMap.reduceValues(2,
value -> value.get(),
Integer::sum
);
System.out.println("总单词数: " + totalWords);
}
/**
* 分段锁机制演示
*/
public static void segmentLockDemo() throws InterruptedException {
System.out.println("\n=== 分段锁机制演示 ===");
ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
// 不同分段的键(通过哈希计算分布在不同的段)
int[] keysInDifferentSegments = {1, 2, 17, 18, 33, 34}; // 假设这些键在不同段
CountDownLatch latch = new CountDownLatch(keysInDifferentSegments.length);
long startTime = System.currentTimeMillis();
for (int key : keysInDifferentSegments) {
new Thread(() -> {
// 模拟对同一个段的操作会竞争,不同段的操作不会竞争
for (int i = 0; i < 1000; i++) {
map.put(key, "value" + i);
}
latch.countDown();
}).start();
}
latch.await();
long endTime = System.currentTimeMillis();
System.out.println("分段操作耗时: " + (endTime - startTime) + "ms");
System.out.println("最终Map大小: " + map.size());
}
/**
* ConcurrentHashMap 在Java 8中的改进
*/
public static void java8Improvements() {
System.out.println("\n=== Java 8+ 改进特性 ===");
ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();
// 初始化一些数据
map.put("A", 1L);
map.put("B", 2L);
map.put("C", 3L);
// forEach - 并行遍历
System.out.println("并行遍历:");
map.forEach(2, (k, v) -> System.out.println(k + " -> " + v));
// reduce - 并行归约
Long sum = map.reduceValues(2, Long::sum);
System.out.println("值总和: " + sum);
// mappingCount - 返回long类型的映射数量
System.out.println("映射数量: " + map.mappingCount());
// 新方法: getOrDefault, putIfAbsent, computeIfAbsent等
Long value = map.getOrDefault("D", 0L);
System.out.println("获取D的值(默认0): " + value);
map.computeIfAbsent("D", k -> 4L);
System.out.println("计算后D的值: " + map.get("D"));
}
public static void main(String[] args) throws Exception {
basicOperations();
performanceTest();
advancedFeatures();
segmentLockDemo();
java8Improvements();
}
}
总结
核心知识点回顾:
-
JUC核心类:
Callable/FutureTask:带返回值的任务执行ReentrantLock:更灵活的锁机制,支持公平锁、Condition等- 线程池:合理管理线程资源,提高性能
Semaphore:控制资源访问的并发数CountDownLatch:多线程协调工具
-
线程安全集合:
CopyOnWriteArrayList:读多写少场景,无锁读取- 各种
BlockingQueue:生产者消费者模式的最佳选择 ConcurrentHashMap:分段锁机制,高并发性能优秀
-
选型建议:
- 根据读写比例选择合适的数据结构
- 考虑数据一致性和性能的平衡
- 合理使用并发工具类简化多线程编程
-
最佳实践:
- 理解各种工具的适用场景
- 注意资源管理和异常处理
- 进行充分的性能测试和监控
这些工具类和集合为构建高性能、高并发的Java应用程序提供了强大的支持。