JUC并发包深度解析:原理、示例与实战场景(一文教会)

JUC并发包深度解析:原理、示例与实战场景

一、AtomicInteger:原子整数操作

1. 底层原理

成功
失败
成功
失败
比较值是否被修改
比较值是否被修改
线程1读取值
执行计算
CAS操作
更新值
重试读取
线程2读取值
执行计算
CAS操作
更新值
重试读取
内存地址V

核心机制:

  • CAS操作(Compare And Swap):通过CPU原子指令保证操作的原子性

  • 自旋重试:当多个线程竞争时,失败的线程会循环重试而非阻塞

  • 内存屏障:保证修改后的值对其他线程立即可见(volatile语义)

2. 代码示例(带详细注释)

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    // 创建原子整数,初始值为0
    private static AtomicInteger counter = new AtomicInteger(0);
    
    public static void main(String[] args) throws InterruptedException {
        // 创建10个线程
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    // 原子自增操作(替代i++)
                    counter.incrementAndGet();
                    
                    /* 等效于以下操作:
                     * int current;
                     * do {
                     *     current = counter.get();  // 读取当前值
                     * } while (!counter.compareAndSet(current, current + 1)); // CAS更新
                     */
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread t : threads) {
            t.join();
        }
        
        System.out.println("最终结果: " + counter.get()); // 正确输出10000
    }
}

3. 实战场景:分布式ID生成器

**需求背景:**在订单系统中需要生成全局唯一ID,要求高性能、无冲突
解决方案:AtomicInteger + 时间戳组合

public class OrderIdGenerator {
    // 原子计数器(每天重置)
    private static AtomicInteger dailyCounter = new AtomicInteger(0);
    // 最后日期记录(避免跨天问题)
    private static volatile String lastDate = "";
    
    public static String generateOrderId() {
        String today = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        
        // 日期变更检测(双重检查锁)
        if (!today.equals(lastDate)) {
            synchronized (OrderIdGenerator.class) {
                if (!today.equals(lastDate)) {
                    dailyCounter.set(0);
                    lastDate = today;
                }
            }
        }
        
        // 组合ID:日期+原子计数(6位补零)
        return today + String.format("%06d", dailyCounter.incrementAndGet());
    }
}

// 使用示例
public class OrderService {
    public Order createOrder() {
        Order order = new Order();
        order.setId(OrderIdGenerator.generateOrderId()); // 生成唯一ID
        // 其他业务逻辑...
        return order;
    }
}

二、ReentrantLock:可重入锁

1. 底层原理

线程请求锁
锁状态=0?
获取锁 state=1
当前线程是持有者?
重入计数增加 state++
加入等待队列
释放锁
state--
state=0?
唤醒等待队列头节点
保持持有状态

核心机制:

  • AQS队列(AbstractQueuedSynchronizer):维护等待线程的CLH队列

  • 可重入性:允许线程多次获取同一把锁

  • 公平性选择:公平锁(FIFO) vs 非公平锁(插队机制)

2. 代码示例(带详细注释)

import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    // 创建可重入锁(默认非公平)
    private static final ReentrantLock lock = new ReentrantLock();
    private static int sharedResource = 0;

    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                lock.lock();  // 获取锁(阻塞直到成功)
                try {
                    // 临界区开始
                    sharedResource++;
                    // 可重入演示
                    if (sharedResource % 100 == 0) {
                        nestedLockDemo();
                    }
                    // 临界区结束
                } finally {
                    lock.unlock();  // 必须在finally中释放锁
                }
            }
        };
        
        new Thread(task).start();
        new Thread(task).start();
    }
    
    private static void nestedLockDemo() {
        lock.lock();  // 可重入获取同一把锁
        try {
            System.out.println("重入层级: " + lock.getHoldCount());
        } finally {
            lock.unlock();
        }
    }
}

3. 实战场景:银行账户转账

需求背景:金融系统中需要保证转账操作的原子性,避免死锁
解决方案:ReentrantLock + 超时控制

public class BankAccount {
    private final String accountId;
    private int balance;
    // 账户专属锁(避免锁整个银行系统)
    private final ReentrantLock lock = new ReentrantLock();
    
    public BankAccount(String accountId, int balance) {
        this.accountId = accountId;
        this.balance = balance;
    }
    
    // 安全的转账操作
    public boolean transferTo(BankAccount target, int amount) {
        // 获取当前时间(用于超时计算)
        long start = System.currentTimeMillis();
        
        while (true) {
            // 尝试获取当前账户锁(带超时)
            if (lock.tryLock(300, TimeUnit.MILLISECONDS)) {
                try {
                    // 尝试获取目标账户锁(带超时)
                    if (target.lock.tryLock(300, TimeUnit.MILLISECONDS)) {
                        try {
                            // 双锁保护下的转账操作
                            if (this.balance >= amount) {
                                this.balance -= amount;
                                target.balance += amount;
                                System.out.printf("%s 向 %s 转账 %d 成功%n", 
                                    accountId, target.accountId, amount);
                                return true;
                            } else {
                                System.out.println("余额不足");
                                return false;
                            }
                        } finally {
                            target.lock.unlock();
                        }
                    }
                } finally {
                    lock.unlock();
                }
            }
            
            // 超时检测
            if (System.currentTimeMillis() - start > 1000) {
                System.out.println("转账超时,请重试");
                return false;
            }
            
            // 随机睡眠避免活锁
            try {
                Thread.sleep(10 + new Random().nextInt(50));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

// 使用示例
public class BankingSystem {
    public static void main(String[] args) {
        BankAccount alice = new BankAccount("A1001", 5000);
        BankAccount bob = new BankAccount("B2002", 3000);
        
        // 并发转账
        new Thread(() -> alice.transferTo(bob, 100)).start();
        new Thread(() -> bob.transferTo(alice, 200)).start();
    }
}

三、BlockingQueue:阻塞队列

1. 底层原理

生产者线程
put操作
队列满?
阻塞等待
加入队列
唤醒消费者
消费者线程
take操作
队列空?
阻塞等待
取出元素
唤醒生产者

核心机制:

  • 双条件队列:notFull(生产者等待条件)和 notEmpty(消费者等待条件)

  • 阻塞/唤醒机制:基于Lock/Condition实现

  • 容量策略:有界队列(ArrayBlockingQueue) vs 无界队列(LinkedBlockingQueue)

2. 代码示例(带详细注释)

import java.util.concurrent.*;

public class BlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建容量为5的阻塞队列
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
        
        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                String[] items = {"A", "B", "C", "D", "E", "F"};
                for (String item : items) {
                    // 如果队列满则阻塞等待
                    queue.put(item); 
                    System.out.println("生产: " + item);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    // 如果队列空则阻塞等待
                    String item = queue.take(); 
                    System.out.println("消费: " + item);
                    Thread.sleep(200);
                    
                    // 队列状态监控
                    System.out.println("队列状态: " + queue);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        producer.start();
        consumer.start();
        
        producer.join();
        consumer.join();
    }
}

3. 实战场景:电商订单处理系统

需求背景:大促期间订单量激增,需要缓冲订单处理压力
解决方案:多层阻塞队列 + 线程池

public class OrderProcessingSystem {
    // 1. 订单接收队列(内存缓冲)
    private final BlockingQueue<Order> orderQueue = new LinkedBlockingQueue<>(1000);
    
    // 2. 订单处理线程池
    private final ExecutorService processorPool = Executors.newFixedThreadPool(8);
    
    // 3. 失败订单队列(持久化存储)
    private final BlockingQueue<Order> failedOrderQueue = new ArrayBlockingQueue<>(100);
    
    public void start() {
        // 启动订单接收服务
        startOrderReceiver();
        
        // 启动订单处理线程
        for (int i = 0; i < 8; i++) {
            processorPool.execute(this::processOrders);
        }
        
        // 启动失败订单重试线程
        new Thread(this::retryFailedOrders).start();
    }
    
    private void startOrderReceiver() {
        new Thread(() -> {
            while (true) {
                try {
                    // 从消息队列获取订单(模拟)
                    Order order = fetchOrderFromMQ();
                    
                    // 放入内存队列(阻塞直到有空间)
                    orderQueue.put(order);
                    System.out.println("接收订单: " + order.getId());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }).start();
    }
    
    private void processOrders() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // 从队列获取订单(阻塞直到有订单)
                Order order = orderQueue.take();
                
                try {
                    // 处理订单(支付、库存扣减等)
                    processOrder(order);
                } catch (Exception e) {
                    // 处理失败放入重试队列
                    failedOrderQueue.put(order);
                    System.err.println("订单处理失败: " + order.getId());
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    private void retryFailedOrders() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // 获取失败订单(带超时)
                Order order = failedOrderQueue.poll(30, TimeUnit.SECONDS);
                if (order != null) {
                    // 重试逻辑(带指数退避)
                    retryOrder(order);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

四、CountDownLatch:倒计时门闩

1. 底层原理

初始化count=3
线程1调用await
检查count>0?
进入等待队列
继续执行
线程2调用countDown
count--
count==0?
唤醒所有等待线程
结束

核心机制:

  • 一次性门闩:计数归零后无法重置

  • 共享锁模式:基于AQS的共享锁实现

  • 无阻塞检查:getCount()方法可随时获取当前计数

2. 代码示例(带详细注释)

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建倒计时门闩(计数=3)
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(3);
        
        // 创建3个工作线程
        for (int i = 0; i < 3; i++) {
            new Thread(new Worker(startSignal, doneSignal, "Worker-" + (i+1))).start();
        }
        
        System.out.println("主线程准备阶段...");
        Thread.sleep(2000);  // 模拟初始化时间
        
        System.out.println("主线程发出启动信号");
        startSignal.countDown();  // 释放所有工作线程
        
        doneSignal.await();  // 等待所有工作线程完成
        System.out.println("所有工作线程已完成任务");
    }
    
    static class Worker implements Runnable {
        private final CountDownLatch startSignal;
        private final CountDownLatch doneSignal;
        private final String name;
        
        Worker(CountDownLatch start, CountDownLatch done, String name) {
            this.startSignal = start;
            this.doneSignal = done;
            this.name = name;
        }
        
        public void run() {
            try {
                System.out.println(name + " 等待启动信号...");
                startSignal.await();  // 等待主线程信号
                
                System.out.println(name + " 开始工作");
                Thread.sleep(1000 + new Random().nextInt(1000));  // 模拟工作
                
                System.out.println(name + " 工作完成");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                doneSignal.countDown();  // 完成任务计数减1
            }
        }
    }
}

3. 实战场景:微服务启动依赖检查

需求背景:系统包含多个微服务,主服务启动前需验证所有依赖服务可用
解决方案:CountDownLatch + 健康检查

public class ServiceInitializer {
    // 依赖服务列表
    private static final List<String> DEPENDENCIES = Arrays.asList(
        "auth-service", 
        "payment-service", 
        "inventory-service"
    );
    
    public void initializeSystem() {
        // 创建门闩(数量=依赖服务数)
        CountDownLatch latch = new CountDownLatch(DEPENDENCIES.size());
        
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(DEPENDENCIES.size());
        
        // 并行检查所有依赖服务
        for (String service : DEPENDENCIES) {
            executor.execute(() -> {
                try {
                    if (checkServiceHealth(service)) {
                        System.out.println(service + " 健康检查通过");
                    } else {
                        System.err.println(service + " 健康检查失败");
                    }
                } finally {
                    latch.countDown();  // 无论成功失败都计数减1
                }
            });
        }
        
        try {
            // 设置超时时间(5秒)
            if (latch.await(5, TimeUnit.SECONDS)) {
                System.out.println("所有服务健康检查完成");
                startMainService();
            } else {
                // 获取未完成的服务
                long missing = latch.getCount();
                System.err.println(missing + " 个服务未完成检查,启动终止");
                
                // 强制关闭线程池
                executor.shutdownNow();
                System.exit(1);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            executor.shutdown();
        }
    }
    
    private boolean checkServiceHealth(String serviceName) {
        // 模拟健康检查(真实场景调用HTTP/健康端点)
        try {
            Thread.sleep(500 + new Random().nextInt(1000));
            return new Random().nextDouble() > 0.2; // 80%成功率
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
}

五、CompletableFuture:异步编程利器

1. 底层原理

主线程
提交异步任务
ForkJoinPool
工作线程1
工作线程2
任务完成
任务完成
触发回调函数
结果组合处理

核心机制:

  • 任务编排:通过链式调用组合多个异步任务

  • 工作窃取线程池:默认使用ForkJoinPool.commonPool()

  • 回调机制:支持thenApply/thenAccept/thenRun等回调方法

  • 组合操作:支持thenCompose/thenCombine/allOf/anyOf等组合方法

2. 代码示例(带详细注释)

import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws Exception {
        // 示例1:基本异步操作
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务执行中..." + Thread.currentThread().getName());
            sleep(1000);  // 模拟耗时操作
            return "Hello";
        });
        
        // 异步结果处理(非阻塞)
        future.thenAccept(result -> System.out.println("结果处理: " + result));
        
        // 示例2:任务链式调用
        CompletableFuture<String> combined = CompletableFuture.supplyAsync(() -> {
            sleep(500);
            return "World";
        })
        .thenApplyAsync(first -> {
            System.out.println("第一阶段结果: " + first);
            return first + " Java";
        })
        .thenCombine(future, (second, first) -> first + " " + second);
        
        System.out.println("最终结果: " + combined.get());
        
        // 示例3:异常处理
        CompletableFuture<Integer> safeFuture = CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) throw new RuntimeException("模拟异常");
            return 42;
        }).exceptionally(ex -> {
            System.err.println("捕获异常: " + ex.getMessage());
            return 0;  // 默认值
        });
        
        System.out.println("安全结果: " + safeFuture.get());
    }
    
    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

3. 实战场景:电商商品详情页聚合

需求背景:商品详情页需聚合商品信息、库存、评价、推荐等6个服务的数据
挑战:服务响应时间差异大(50ms~2s),需要并行调用
解决方案:CompletableFuture多服务并行调用

public class ProductDetailService {
    // 并行获取所有服务数据
    public ProductDetail loadProductDetail(String productId) {
        // 1. 创建各服务的异步任务
        CompletableFuture<ProductInfo> infoFuture = CompletableFuture.supplyAsync(
            () -> productService.getInfo(productId));
        
        CompletableFuture<Integer> stockFuture = CompletableFuture.supplyAsync(
            () -> inventoryService.getStock(productId));
        
        CompletableFuture<List<Review>> reviewsFuture = CompletableFuture.supplyAsync(
            () -> reviewService.getReviews(productId));
        
        CompletableFuture<List<Recommendation>> recommendsFuture = CompletableFuture.supplyAsync(
            () -> recommendService.getRecommends(productId));
        
        CompletableFuture<PriceInfo> priceFuture = CompletableFuture.supplyAsync(
            () -> priceService.getPriceInfo(productId));
        
        CompletableFuture<Promotion> promotionFuture = CompletableFuture.supplyAsync(
            () -> promotionService.getPromotion(productId));
        
        // 2. 等待所有任务完成(带超时)
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
            infoFuture, stockFuture, reviewsFuture, 
            recommendsFuture, priceFuture, promotionFuture
        );
        
        try {
            // 设置总超时时间(800ms)
            allFutures.get(800, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            // 部分服务超时处理
            System.err.println("部分服务响应超时,返回降级数据");
        } catch (Exception e) {
            throw new RuntimeException("聚合失败", e);
        }
        
        // 3. 构建返回结果(即使部分失败也返回可用数据)
        return ProductDetail.builder()
            .info(getOrNull(infoFuture))
            .stock(getOrNull(stockFuture))
            .reviews(getOrNull(reviewsFuture))
            .recommendations(getOrNull(recommendsFuture))
            .priceInfo(getOrNull(priceFuture))
            .promotion(getOrNull(promotionFuture))
            .build();
    }
    
    // 安全获取结果(避免异常传播)
    private <T> T getOrNull(CompletableFuture<T> future) {
        try {
            return future.getNow(null);  // 立即获取当前结果
        } catch (Exception e) {
            return null;
        }
    }
}

// 使用示例
public class ProductController {
    @GetMapping("/product/{id}")
    public ProductDetail getDetail(@PathVariable String id) {
        return new ProductDetailService().loadProductDetail(id);
    }
}

六、Semaphore:资源访问控制器

1. 底层原理

线程请求资源
可用资源>0?
资源计数减1
执行任务
释放资源
资源计数加1
加入等待队列
释放资源
等待队列空?
增加资源计数
唤醒等待线程

核心机制:

  • 资源许可证:每个线程需获取许可证才能访问资源

  • 公平性选择:支持公平/非公平两种模式

  • 可中断获取:支持带超时的tryAcquire方法

  • 信号量回收:释放许可证后可供其他线程使用

2. 代码示例(带详细注释)

import java.util.concurrent.*;

public class SemaphoreExample {
    public static void main(String[] args) {
        // 创建信号量(3个许可证)
        Semaphore semaphore = new Semaphore(3, true);  // 公平模式
        
        // 创建10个线程竞争资源
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executor.execute(new ResourceUser(semaphore, "Worker-" + i));
        }
        
        executor.shutdown();
    }
    
    static class ResourceUser implements Runnable {
        private final Semaphore semaphore;
        private final String name;
        
        ResourceUser(Semaphore semaphore, String name) {
            this.semaphore = semaphore;
            this.name = name;
        }
        
        public void run() {
            try {
                System.out.println(name + " 等待获取资源...");
                
                // 尝试在2秒内获取许可(避免永久阻塞)
                if (semaphore.tryAcquire(2, TimeUnit.SECONDS)) {
                    try {
                        System.out.println(name + " 获取资源成功! 剩余许可: " 
                            + semaphore.availablePermits());
                        
                        // 模拟资源使用
                        Thread.sleep(1000 + new Random().nextInt(1000));
                    } finally {
                        semaphore.release();  // 必须释放
                        System.out.println(name + " 释放资源");
                    }
                } else {
                    System.err.println(name + " 获取资源超时!");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

3. 实战场景:API限流系统

需求背景:第三方支付接口限制每秒最大调用次数(100次/秒)
挑战:突发流量可能导致服务被禁用
解决方案:Semaphore + 定时重置

public class RateLimiter {
    // 每秒最大请求数
    private final int maxPermitsPerSecond;
    // 当前可用的许可证
    private volatile Semaphore semaphore;
    
    public RateLimiter(int maxPermitsPerSecond) {
        this.maxPermitsPerSecond = maxPermitsPerSecond;
        this.semaphore = new Semaphore(maxPermitsPerSecond);
        startResetTask();
    }
    
    // 尝试执行受保护的API调用
    public <T> T callWithLimit(Callable<T> task) throws Exception {
        if (semaphore.tryAcquire()) {
            try {
                return task.call();  // 执行受保护的API调用
            } finally {
                // 不需要手动释放,通过定时器重置
            }
        } else {
            throw new RateLimitExceededException("API调用频率超过限制");
        }
    }
    
    // 每秒重置信号量
    private void startResetTask() {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
            int current = semaphore.availablePermits();
            int needRelease = maxPermitsPerSecond - current;
            
            if (needRelease > 0) {
                semaphore.release(needRelease);  // 补充许可证
            }
        }, 0, 1, TimeUnit.SECONDS);  // 每秒触发
    }
}

// 使用示例
public class PaymentService {
    private final RateLimiter rateLimiter = new RateLimiter(100);
    
    public PaymentResult processPayment(PaymentRequest request) {
        try {
            return rateLimiter.callWithLimit(() -> {
                // 调用第三方支付API
                return thirdPartyPaymentAPI.process(request);
            });
        } catch (RateLimitExceededException e) {
            // 触发降级策略
            return localFallback(request);
        } catch (Exception e) {
            throw new PaymentException("支付失败", e);
        }
    }
}

总结:JUC组件选型指南

场景特征推荐组件原因说明
简单计数器AtomicInteger轻量无锁,性能高
资源互斥访问ReentrantLock灵活控制,支持条件等待
生产者-消费者模式BlockingQueue天然解耦,自动流量控制
多任务等待CountDownLatch简单可靠,一次性协调
循环多阶段任务CyclicBarrier可重用,支持回调
资源池管理Semaphore精准控制并发数量
异步任务链CompletableFuture函数式编程,链式调用

最佳实践原则:

  • 优先无锁:能用原子类解决的问题不用锁

  • 锁粒度最小化:减小临界区范围

  • 超时控制:所有阻塞操作必须设置超时

  • 资源清理:finally块中释放锁和资源

  • 线程命名:通过线程工厂命名线程,便于诊断

高级应用技巧

1. CompletableFuture组合技巧

// 多结果合并(等待所有任务完成)
CompletableFuture<Void> all = CompletableFuture.allOf(future1, future2, future3);

// 任一完成(返回第一个完成的结果)
CompletableFuture<Object> any = CompletableFuture.anyOf(future1, future2);

// 结果转换链
CompletableFuture<String> pipeline = CompletableFuture.supplyAsync(() -> 100)
    .thenApplyAsync(result -> result * 2)         // 异步转换
    .thenCompose(value -> CompletableFuture.supplyAsync(() -> "结果:" + value))
    .handle((result, ex) -> ex != null ? "默认值" : result); // 异常处理

2. Semaphore高级模式

// 资源池实现
class ConnectionPool {
    private final Semaphore semaphore;
    private final BlockingQueue<Connection> pool;
    
    public ConnectionPool(int size) {
        semaphore = new Semaphore(size, true); // 公平模式
        pool = new ArrayBlockingQueue<>(size);
        for (int i = 0; i < size; i++) {
            pool.add(createConnection());
        }
    }
    
    public Connection acquire() throws InterruptedException {
        semaphore.acquire();  // 获取访问许可
        return pool.take();    // 获取实际资源
    }
    
    public void release(Connection conn) {
        pool.offer(conn);      // 归还资源
        semaphore.release();   // 释放许可
    }
}

// 动态调整许可数
public void resize(int newSize) {
    int delta = newSize - semaphore.availablePermits();
    if (delta > 0) {
        semaphore.release(delta);  // 增加许可
    } else {
        semaphore.reducePermits(-delta); // 减少许可
    }
}

3. 监控与调试

// CompletableFuture链监控
pipeline.whenComplete((res, ex) -> {
    if (ex != null) {
        logger.error("Pipeline failed", ex);
    } else {
        logger.info("Pipeline result: {}", res);
    }
});

// Semaphore状态监控
public void monitorSemaphore(Semaphore sem) {
    System.out.println("可用许可: " + sem.availablePermits());
    System.out.println("等待线程数: " + sem.getQueueLength());
}

// 统一异常处理
CompletableFuture.supplyAsync(() -> {
    // 业务代码
}).exceptionally(ex -> {
    metrics.counter("async_errors").increment();
    return fallbackValue();
});

生产环境建议:

  • 使用-Djdk.tracePinnedThreads参数检测CompletableFuture线程阻塞

  • 重要业务实现熔断降级机制,避免级联故障

  • 对Semaphore设置监控告警(许可证不足、等待队列过长)

  • 使用MDC(Mapped Diagnostic Context)传递异步任务上下文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值