java锁,同步器,JUC并发包的工具实际的可以用在那些现实场景

 

一、同步器

 

  1. CountDownLatch

    1. 选择等待,直到为0:让线程等待直到持续减一计数器归零,这个等待的线程既可以是主线程,也可以是子线程。 
    2. 方法:它的构造方法,会传入一个 count 值,用于计数。当一个线程调用await方法时,就会阻塞当前线程。每当有线程调用一次 countDown 方法时,计数就会减 1。当 count 的值等于 0 的时候,被阻塞的线程才会继续运行。
    3. 实际场景
      1. 服务启动依赖检查:主线程需要等待所有组件(数据库连接、缓存加载、配置文件读取)初始化完成后,才能启动服务。

        CountDownLatch latch = new CountDownLatch(3);
        // 组件1初始化完成后调用 latch.countDown()
        // 组件2、3同理...
        latch.await(); // 主线程阻塞,直到计数器归零
        startServer(); // 所有组件就绪后启动服务
      2. 测试并发场景:模拟高并发请求时,确保所有线程就绪后再同时发起请求。

        CountDownLatch startLatch = new CountDownLatch(1);
        for (int i = 0; i < threadCount; i++) {
          new Thread(() -> {
            startLatch.await(); // 所有线程在此等待
            sendRequest();      // 收到信号后同时发起请求
          }).start();
        }
        Thread.sleep(5000);    // 模拟准备时间
        startLatch.countDown(); // 释放所有线程
      3. 并行任务汇总:主线程需要等待所有子任务完成后再汇总结果。

        CountDownLatch taskLatch = new CountDownLatch(taskCount);
        for (Task task : tasks) {
          executor.submit(() -> {
            try { task.execute(); }
            finally { taskLatch.countDown(); }
          });
        }
        taskLatch.await(); // 等待所有任务结束
        generateSummaryReport();
      4. 火箭发射,工程师需完成10项检查(每个检查完成后countDown()),指挥员(主线程)在控制台await(),直到所有检查通过才按下发射按钮。
      5. 总统选举,等到每个选民投出一票,总统才能上任。
  2. CyclicBarrier

    1. 相互等待,同时执行:让一组线程相互等待到屏障点「某个线程到达某个点了,执行await()被阻塞等待」
    2. 方法:
      1. 第一个构造的参数,指的是需要几个线程一起到达,才可以使所有线程取消等待。第二个构造,额外指定了一个参数,用于在所有线程达到屏障时,优先执行 barrierAction
    3. 实际场景:
      1. 多轮次游戏同步:游戏服务器等待所有玩家完成一局操作后,再开始下一轮。
        CyclicBarrier roundBarrier = new CyclicBarrier(playerCount);
        while (gameRunning) {
          for (Player player : players) {
            executor.execute(() -> {
              player.makeMove();     // 玩家操作
              roundBarrier.await();  // 等待所有玩家操作结束
            });
          }
        }
      2. 数据分批次处理:将大数据分片,多个线程处理完当前批次后,每个阶段的计算都依赖于前一阶段的结果,才能执行下一批。在并行计算中的应用
        CyclicBarrier batchBarrier = new CyclicBarrier(threadCount);
        while (hasNextBatch()) {
          for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
              processBatchData();
              batchBarrier.await(); // 等待本批次所有线程处理完成
            }).start();
          }
        }
  3. Semaphore

    1. 控制同时访问资源的线程数量
    2. 方法
      1. 构造器: boolean 值的参数,控制抢锁是否是公平
        public Semaphore(int permits) {
            sync = new NonfairSync(permits);
        }
        public Semaphore(int permits, boolean fair) {
            sync = fair ? new FairSync(permits) : new NonfairSync(permits);
        }
      2. semaphore.acquire(); //获得令牌
      3. semaphore.release(); //释放令牌
    3. 实际场景:
      1. 限流:
        1. 接口限流:防止突发流量压垮第三方API(如支付接口),令牌桶算法。
          Semaphore rateLimiter = new Semaphore(100); // 每秒100个请求
          void callExternalAPI() {
          if (rateLimiter.tryAcquire(1, TimeUnit.SECONDS)) {
          sendRequest();
          } else { throw new RateLimitExceededException(); }
          }
        2. 数据库连接池:限制同时使用的数据库连接数,避免资源耗尽。
          Semaphore dbSemaphore = new Semaphore(10); // 最多10个连接
          void queryDatabase() {
            dbSemaphore.acquire(); // 获取许可证
            try { executeSQL(); } 
            finally { dbSemaphore.release(); } // 释放许可证
          }
      2. 生活场景:
        1. 停车场管理系统:模拟有限车位,车辆进入/离开时占用/释放信号量。第三方
          Semaphore parkingLot = new Semaphore(50); // 50个车位
          void carEnter() {
            parkingLot.acquire(); // 获取车位
            parkCar();
          }
          void carExit() {
            leaveParking();
            parkingLot.release(); // 释放车位
          }
      3. 阿萨德
  4. Exchanger(交换器)

    1. 严格2个线程
    2. 双线程数据交换(如生产者-消费者缓冲区交换)
      1. 生产者填满缓冲区 → 交换给消费者
        消费者处理数据 → 返回空缓冲区给生产者
        避免使用共享队列,实现直接传递

        // 两个线程交换数据 :cite[1]
        import java.util.concurrent.Exchanger;
        
        public class DataExchangeExample {
            private static final Exchanger<String> exchanger = new Exchanger<>();
        
            public static void main(String[] args) {
                new Thread(() -> {
                    try {
                        String dataA = "Data from Thread-A";
                        String received = exchanger.exchange(dataA); // 阻塞直到交换
                        System.out.println("Thread-A收到: " + received);
                    } catch (InterruptedException e) { e.printStackTrace(); }
                }).start();
        
                new Thread(() -> {
                    try {
                        String dataB = "Data from Thread-B";
                        String received = exchanger.exchange(dataB);
                        System.out.println("Thread-B收到: " + received);
                    } catch (InterruptedException e) { e.printStackTrace(); }
                }).start();
            }
        }

        输出:
        Thread-A收到: Data from Thread-B  
        Thread-B收到: Data from Thread-A
         

         

    3. 流水线处理系统

        • 线程A处理阶段1 → 交换中间结果给线程B

        • 线程B处理阶段2 → 返回处理结果

    4. 校对/校验系统

      1. 两个线程独立计算同一份数据

      2. 在交换点比对计算结果是否一致

  5. Phaser(移相器)

    1. 关键点:arriveAndAwaitAdvance() 线程阻塞进入同步阶段,直到所有线程都到同步阶段,自动开始下一阶段,onAdvance() 定义阶段结束条件,直到arriveAndDeregister的线程的线程数量满足结束条件,整体结束。
    2. 持动态增减线程,动态注册(1-N个线程),随时注册/注销参与者
    3. 多阶段游戏/仿真系统

      1. 游戏关卡:准备阶段 → 战斗阶段 → 结算阶段

      2. 玩家可随时加入/退出游戏

      3.  

        package dto.Phaser;
        
        import java.util.concurrent.Phaser;
        
        public class GameServer {
            private static final Phaser phaser = new Phaser(1) { // 主线程注册
                @Override
                protected boolean onAdvance(int phase, int parties) {
                    System.out.println("===== 主线程阶段" + phase + "完成 =====\n");
                    return phase >= 2; // 2阶段后终止
                }
            };
        
            public static void main(String[] args) {
                startGame();
            }
        
            static void startGame() {
                // 阶段0:准备阶段
                System.out.println("游戏准备中...");
                spawnPlayers(3); // 加入3个玩家
                System.out.println("等待所有玩家准备,主线程等待");
                phaser.arriveAndAwaitAdvance(); // 等待所有玩家准备
        
                // 阶段1:战斗阶段
                System.out.println("\n战斗开始!");
                spawnPlayers(2); // 中途加入2个玩家
                System.out.println("等待所有玩家战斗阶段,主线程等待");
                phaser.arriveAndAwaitAdvance();
        
                // 阶段2:结算阶段
                System.out.println("\n战斗结束,结算奖励,主线程退出");
                phaser.arriveAndDeregister(); // 主线程退出
            }
        
            static void spawnPlayers(int count) {
                for (int i = 0; i < count; i++) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    int playerId = phaser.getRegisteredParties();
                    new Thread(() -> {
                        phaser.register(); // 动态注册玩家
                        System.out.println("玩家" + playerId + "加入游戏");
        
                        // 阶段0:准备
                        doAction("准备资源,子线程等待");
                        phaser.arriveAndAwaitAdvance();
        
                        // 阶段1:战斗
                        doAction("攻击敌人,子线程等待");
                        phaser.arriveAndAwaitAdvance();
        
                        // 阶段2:结算
                        doAction("领取奖励,子线程退出");
                        phaser.arriveAndDeregister(); // 注销玩家
                    }).start();
                }
            }
        
            static void doAction(String action) {
                try {
                    System.out.println(Thread.currentThread().getName() + "执行: " + action);
                    Thread.sleep((long) (Math.random() * 2000));
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        
        
        游戏准备中...
        玩家1加入游戏
        Thread-0执行: 准备资源,子线程等待
        玩家2加入游戏
        Thread-1执行: 准备资源,子线程等待
        等待所有玩家准备,主线程等待
        玩家3加入游戏
        Thread-2执行: 准备资源,子线程等待
        ===== 主线程阶段0完成 =====
        
        Thread-2执行: 攻击敌人,子线程等待
        Thread-1执行: 攻击敌人,子线程等待
        Thread-0执行: 攻击敌人,子线程等待
        
        战斗开始!
        玩家4加入游戏
        Thread-3执行: 准备资源,子线程等待
        等待所有玩家战斗阶段,主线程等待
        玩家5加入游戏
        Thread-4执行: 准备资源,子线程等待
        ===== 主线程阶段1完成 =====
        
        Thread-4执行: 攻击敌人,子线程等待
        Thread-3执行: 攻击敌人,子线程等待
        Thread-1执行: 领取奖励,子线程退出
        Thread-2执行: 领取奖励,子线程退出
        
        战斗结束,结算奖励,主线程退出
        Thread-0执行: 领取奖励,子线程退出
        ===== 主线程阶段2完成 =====
        
        Thread-4执行: 领取奖励,子线程退出
        Thread-3执行: 领取奖励,子线程退出

         

    4. 科学计算工作流

      1. 阶段1:数据加载 → 阶段2:并行计算 → 阶段3:结果汇总

      2. 动态增减计算节点

    5. 分布式任务协调

      1. 主任务分发给工作节点

      2. 等待所有节点完成当前阶段 → 进入下一阶段

      3. 节点故障时自动注销

    6. 特性ExchangerPhaser
      参与者数量 严格2个线程 动态注册(1-N个线程)
      同步方向 双向数据交换 多阶段单向屏障
      重用性 可重复交换 自动重置阶段计数器
      动态调整 ❌ 固定2方 ✅ 随时注册/注销参与者
      适用场景 双线程流水线 多阶段任务(如游戏关卡/科学计算)
      复杂任务协调 ✅ 支持分层、终止条件、回调函数

二、基础锁 (Locks)

  1. synchronized 关键字 (内置锁)

    1. 延迟初始化一个昂贵的资源:确保只有一个线程能执行初始化代码(配合 volatile 解决可见性问题)。
      1. 初始化单例模式
      2. 初始化数据库连接池
    2. 保护共享集合 
      1. ConcurrentHashMap:子方法
      2. HashMap:子方法
    3. 简单对象状态保护
  1. ReentrantLock (可重入锁):

    1. 死锁避免策略,尝试获取锁 (tryLock)
      1. 使用 tryLock() 设置超时,如果线程 A 在一定时间内无法获取 L2,它可以释放 L1 并回退/重试,避免死锁僵局。死锁避免策略。线程 A 持有锁 L1,尝试获取锁 L2;线程 B 持有锁 L2,尝试获取锁 L1。
    2. 公平锁:资源分配需要严格按请求顺序进行,避免线程饥饿。
      1. 比如一个低延迟的交易系统中,保证先到的订单请求优先获得处理权。
    3. 可中断的锁获取 (lockInterruptibly)
      1.  等待该锁的其他线程可以使用 lockInterruptibly() 来获取锁,这样在等待过程中如果被中断(用户取消),可以立即响应中断,而不是一直傻等。
      2. private final ReentrantLock lock = new ReentrantLock();
      3. lock.lockInterruptibly(); // 可中断获取锁
      4. thread2.interrupt(); // 中断线程 thread2 的等待
      5. catch (InterruptedException e) 捕获thread2的中断异常。
        1. 场景:一个长时间运行的任务持有锁,用户可能想取消该任务。
    4. 需要绑定多个条件 (Condition)
      1. 实现一个有界阻塞队列。
        1. 队列满时,put 操作需要等待 (notFull.await());队列空时,get 操作需要等待 (notEmpty.await())。ReentrantLock 可以创建多个 Condition 对象 (notFull, notEmpty) 来精确控制不同条件下的等待/唤醒,比 wait()/notifyAll() 更灵活高效。
          //  有界阻塞队列(ArrayBlockingQueue 原理)
          //  当线程需要基于不同的条件挂起或唤醒时(例如生产者消费者模型中的“非满”和“非空”条件),Condition 允许多个独立的等待队列共存。
          
          
          
          public class BoundedBlockingQueue {
              private final ReentrantLock lock = new ReentrantLock();
              private final Condition notFull = lock.newCondition();  // 队列非满条件
              private final Condition notEmpty = lock.newCondition(); // 队列非空条件
              private final Object[] items;
              private int count;
          
              public BoundedBlockingQueue(int capacity) {
                  items = new Object[capacity];
              }
          
              // 生产者:入队
              public void put(Object x) throws InterruptedException {
                  lock.lock();
                  try {
                      while (count == items.length) 
                          notFull.await(); // 队列满时挂起生产者(等待notFull条件)
                      
                      items[count++] = x;
                      notEmpty.signal(); // 入队后唤醒消费者(满足notEmpty条件)
                  } finally {
                      lock.unlock();
                  }
              }
          
              // 消费者:出队
              public Object take() throws InterruptedException {
                  lock.lock();
                  try {
                      while (count == 0) 
                          notEmpty.await(); // 队列空时挂起消费者(等待notEmpty条件)
                      
                      Object x = items[--count];
                      notFull.signal(); // 出队后唤醒生产者(满足notFull条件)
                      return x;
                  } finally {
                      lock.unlock();
                  }
              }
          }
        2. 状态依赖的线程协调:当线程需要等待系统进入特定状态才执行时(如任务必须等待资源初始化完成):
          class ResourceManager {
              private boolean isReady = false;
              private final ReentrantLock lock = new ReentrantLock();
              private final Condition resourceReady = lock.newCondition();
          
              public void initResource() {
                  lock.lock();
                  try {
                      // 初始化资源...
                      isReady = true;
                      resourceReady.signalAll(); // 唤醒所有等待线程
                  } finally {
                      lock.unlock();
                  }
              }
          
              public void doTask() throws InterruptedException {
                  lock.lock();
                  try {
                      while (!isReady) {
                          resourceReady.await(); // 等待资源就绪
                      }
                      // 执行任务...
                  } finally {
                      lock.unlock();
                  }
              }
          }
        3. 线程按顺序执行:控制线程执行顺序(如 A→B→C):
          class OrderedExecutor {
              private int flag = 1; // 1:允许A执行, 2:允许B执行, 3:允许C执行
              private final ReentrantLock lock = new ReentrantLock();
              private final Condition condA = lock.newCondition();
              private final Condition condB = lock.newCondition();
              private final Condition condC = lock.newCondition();
          
              public void executeA() throws InterruptedException {
                  lock.lock();
                  try {
                      while (flag != 1) condA.await();
                      System.out.println("A");
                      flag = 2;
                      condB.signal(); // 唤醒B
                  } finally {
                      lock.unlock();
                  }
              }
          
              public void executeB() throws InterruptedException {
                  lock.lock();
                  try {
                      while (flag != 2) condB.await();
                      System.out.println("B");
                      flag = 3;
                      condC.signal(); // 唤醒C
                  } finally {
                      lock.unlock();
                  }
              }
              // executeC() 类似...
          }

        4. 能力ConditionObject.wait()/notify()
          多等待队列 ✅ 支持多个条件(如 notFullnotEmpty ❌ 仅1个等待队列
          精准唤醒 ✅ signal() 唤醒同一条件的线程 ❌ notify() 随机唤醒一个
          超时等待 ✅ awaitNanos()awaitUntil() ❌ 仅支持无限等待
          响应中断 ✅ await() 响应中断 ✅ wait() 响应中断
          公平性支持 ✅ 与 ReentrantLock 公平策略绑定 ❌ 无公平性控制

        5. 关键实践原则

          1. 总是用 while 检查条件

            while (!condition) {
              cond.await(); // 防止虚假唤醒(Spurious Wakeup)
            }

          2. 先获取锁再调用 await/signal,未持有锁时调用会抛 IllegalMonitorStateException。

          3. 优先使用 signal() 而非 signalAll(),避免无效唤醒(除非明确需要唤醒所有线程)。

  2. StampedLock

    1. StampedLock 有三种读写方法:

      • readLock:读锁,用于多线程并发读取共享资源。
      • writeLock:写锁,用于独占写入共享资源。
      • tryOptimisticRead:读乐观锁,用于在不阻塞其他线程的情况下尝试读取共享资源。
    2. // 创建 StampedLock 实例
      StampedLock lock = new StampedLock();
      // 获取乐观读锁
      long stamp = lock.tryOptimisticRead(); 
      // 读取共享变量
      if (!lock.validate(stamp)) { // 检查乐观读锁是否有效
          stamp = lock.readLock(); // 如果乐观读锁无效,则获取悲观读锁
          try {
              // 重新读取共享变量
          } finally {
              lock.unlockRead(stamp); // 释放悲观读锁
          }
      }
      
      // 获取悲观读锁
      long stamp = lock.readLock(); 
      try {
          // 读取共享变量
      } finally {
          lock.unlockRead(stamp); // 释放悲观读锁
      }
      
      // 获取写锁
      long stamp = lock.writeLock(); 
      try {
          // 写入共享变量
      } finally {
          lock.unlockWrite(stamp); // 释放写锁
      }

       

三、JUC 并发工具类

  1. ExecutorService / ThreadPoolExecutor (线程池):

    • 场景:几乎所有需要异步或并行执行任务的场景

      • 例子:

        • Web 服务器:使用线程池处理 HTTP 请求。每个请求由一个线程处理,线程池复用线程,避免频繁创建销毁线程的开销。

        • 后台任务处理:发送邮件、生成报表、数据清洗等耗时操作,提交给线程池异步执行,不阻塞主线程。

        • 并行计算:将大任务拆分成小任务,提交给线程池并行执行,提高计算速度。

  2. Future / CompletableFuture (异步结果):

    • 场景:需要获取异步任务结果或进行链式异步调用

      • 例子:

        • Future: 向线程池提交一个计算任务,主线程在需要结果时调用 future.get() 获取(可能阻塞等待)。

        • CompletableFuture: 组合多个异步操作。例如:先异步查询用户信息 (cf1), 查询到后根据用户信息异步查询订单 (cf2 = cf1.thenCompose(user -> getOrdersAsync(user))), 两个都完成后异步发送通知 (cf1.thenCombine(cf2, (user, orders) -> sendNotification(user, orders)))。构建非阻塞、响应式流程。

          • 要求所有请求成功没成功3s返回
            ExecutorService executor = Executors.newCachedThreadPool();
            List<CompletableFuture<Result>> futures = new ArrayList<>();
            
            // 1. 提交所有请求任务
            for (Request request : requests) {
                futures.add(CompletableFuture.supplyAsync(() -> {
                    try {
                        return processRequest(request); // 实际业务处理
                    } catch (Exception e) {
                        return Result.failure(e);       // 捕获所有异常
                    }
                }, executor));
            }
            
            // 2. 创建总超时控制
            CompletableFuture<Void> allDone = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0])
            );
            
            try {
                // 3. 关键:设置3秒全局超时
                allDone.get(3, TimeUnit.SECONDS); // 阻塞直到所有完成或超时
            } catch (TimeoutException e) {
                // 4. 超时处理:取消未完成的任务
                futures.forEach(f -> f.cancel(true)); // true表示中断线程
            } catch (InterruptedException | ExecutionException e) {
                // 其他异常处理
            }
            
            // 5. 收集结果(已完成的任务返回结果,未完成的返回超时标识)
            List<Result> results = futures.stream().map(f -> {
                return f.isDone() ? f.join() : Result.timeout(); 
            }).collect(Collectors.toList());

            方案优势

            能力实现效果
            严格3秒返回 无论成功失败,3秒必响应
            资源控制 自动取消超时任务释放资源
            异常安全 统一处理业务异常和超时
            结果完整性 返回所有请求状态(成功/失败/超时)
            现代API 避免 synchronized/wait() 等底层操作

            对比其他同步器方案

            同步器问题本方案优势
            CountDownLatch 需手动计数,无法取消阻塞线程 自动任务取消
            CyclicBarrier 超时处理复杂,不适合动态任务 简洁超时控制
            Future.get() 单个超时控制,无法批量管理 统一批量管理
            Object.wait() 需配合synchronized,易死锁 无锁安全
  3. ConcurrentHashMap (并发哈希表):

    • 场景:高并发读写的键值对存储

      • 例子:

        • 全局缓存:存储应用配置、热点数据(如商品信息)。支持高并发读取和更新(如使用 compute/merge 原子更新)。

        • 会话存储:Web 应用中存储用户 Session 对象。

        • 计数器:利用 compute 或 merge 方法实现线程安全的计数器(如 map.merge(key, 1, Integer::sum))。

  4. CopyOnWriteArrayList / CopyOnWriteArraySet (写时复制集合):    线程安全集合之CopyOnWriteArrayList详解

    • 场景:读多写少,且要求遍历时快照一致性

      • 例子:

        • 监听器列表:事件源维护一个监听器列表。注册/注销监听器(写)操作较少,触发事件(遍历通知所有监听器 - 读)操作频繁。CopyOnWriteArrayList 保证遍历时看到的是注册/注销操作发生时刻的完整快照,避免了遍历时加锁,且写操作不影响正在进行的遍历。

        • 只读为主的白名单/黑名单:名单更新不频繁,但查询非常频繁。

  5. BlockingQueue 及其实现 (阻塞队列):

    • 场景:生产者-消费者模型

      • 例子:

        • ArrayBlockingQueue / LinkedBlockingQueue: 任务队列。线程池内部的核心组件。生产者线程提交任务(offer()/put()),消费者线程(工作线程)从队列中获取任务(poll()/take())执行。队列满时生产者阻塞,队列空时消费者阻塞。

        • SynchronousQueue: 直接传递。生产者必须等待消费者准备好接收(调用 take()),才能 put() 成功。实现线程间直接、无缓冲的手递手传递,常用于要求高吞吐、低延迟且消费者能力足够强的线程池 (Executors.newCachedThreadPool)。

        • PriorityBlockingQueue: 带优先级的任务队列。例如,处理不同优先级的日志消息或订单。

          • 线程安全通过 ReentrantLock 保证,扩容时使用 CAS 自旋锁优化
          • 方法行为
            offer(E e) 插入元素(自动扩容)
            take() 阻塞获取队首元素(队列空时阻塞)
            poll() 非阻塞获取队首元素(队列空返回 null
          • 使用场景

            1. 任务优先级调度:高优先级任务优先执行(如紧急告警)。

            2. 资源分配:按优先级分配资源(如带宽控制)

        • DelayQueue: 延迟任务调度。元素只有在其指定的延迟时间过后才能被取出。实现定时任务调度器、缓存过期失效等。

          •   
            方法行为
            offer(E e) 插入元素(永不阻塞)
            take() 阻塞直到获取到期元素
            poll() 非阻塞获取到期元素(无到期元素返回 null
            poll(timeout) 超时阻塞获取元素
  6. AtomicXxx (原子类):

    • 场景:无锁状态更新、计数器、标志位

      • 例子:

        • AtomicInteger / AtomicLong: 高性能计数器(如统计访问量、生成全局唯一递增 ID - incrementAndGet())。

        • AtomicBoolean: 简单的开关标志(如 isRunning)。

        • AtomicReference: 原子更新对象引用(如实现无锁栈 push/pop 的核心)。

        • LongAdder / DoubleAdder (JDK8+): 超高并发下的累加器(如统计点击数),性能远优于 AtomicLong,通过分散热点减少竞争。

总结与选择建议

  • 简单互斥: 首选 synchronized。如果够用且性能可接受,就用它,代码简洁。

  • 高级锁需求 (尝试锁、公平锁、可中断锁、多条件): 使用 ReentrantLock

  • 等待线程组完成一次任务: 用 CountDownLatch (一次性)。

  • 等待线程组完成多个阶段的任务: 用 CyclicBarrier (可重用) 或更灵活的 Phaser

  • 控制并发访问资源数量: 用 Semaphore (资源池、限流)。

  • 线程间交换数据缓冲区: 考虑 Exchanger (两方)。

  • 异步执行任务: 必用 线程池 (ExecutorService)。

  • 获取异步结果、编排异步操作: 用 Future (简单) 或 CompletableFuture (强大组合)。

  • 高并发键值存储: 必用 ConcurrentHashMap

  • 读多写少且需遍历快照一致性的集合: 用 CopyOnWriteArrayList/CopyOnWriteArraySet

  • 生产者-消费者: 必用 BlockingQueue (选具体实现)。

  • 无锁计数器/状态更新: 首选 AtomicXxx 类或 LongAdder

 
posted @ 2025-06-12 13:23  飘来荡去evo  阅读(16)  评论(0)    收藏  举报