You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用CountDownLatch控制线程,实现列表按调用顺序添加消息?

问题分析与修正方案

原代码意图通过CountDownLatch实现:前3个线程执行完成后,再启动后续线程(updateThread、threadName4),同时保证线程向列表添加元素的逻辑正确。但原代码存在几个关键问题:

  • 复用同一个CountDownLatch:前三线程执行完成后,latch计数已归零,后续调用latch.await()会直接返回,无法起到等待threadName4的作用
  • ArrayList非线程安全:多线程并发添加元素可能导致数据丢失或并发修改异常
  • createUpdateThread无同步控制:其执行可能和后续线程产生交叉,破坏预期的执行顺序

结合需求(线程启动的特定顺序并非关键,核心是保证前三线程完成后再执行后续线程),以下是修正后的实现:

修正后的代码

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadExample {
    // 使用线程安全的CopyOnWriteArrayList避免并发问题
    private static List<String> resultList = new CopyOnWriteArrayList<>();
    
    public static void main(String[] args) {
        // 第一个latch:等待前3个线程完成
        CountDownLatch preLatch = new CountDownLatch(3);

        // 创建并启动前3个线程
        createThread("threadName1", "message1", preLatch);
        createThread("threadName2", "message2", preLatch);
        createThread("threadName3", "message3", preLatch);

        try {
            // 等待前3个线程全部执行完成
            preLatch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }

        // 前3个线程完成后,启动updateThread并等待其执行完毕
        createUpdateThread("updateThread", "finishThread");
        
        // 验证前3个线程的元素已添加
        if (resultList.size() < 3) {
            throw new IllegalStateException("The size of the list is not at least 3.");
        }

        // 第二个latch:等待threadName4完成
        CountDownLatch postLatch = new CountDownLatch(1);
        createThread("threadName4", "message4", postLatch);

        try {
            // 等待threadName4执行完成
            postLatch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }

        System.out.println("Result List: " + resultList);
    }

    private static void createThread(String threadName, String message, CountDownLatch latch) {
        Thread thread = new Thread(() -> {
            resultList.add(threadName);
            latch.countDown();
            // 这里可以添加业务逻辑
        });
        thread.start();
    }

    private static void createUpdateThread(String updateThread, String finishThread) {
        Thread thread = new Thread(() -> {
            resultList.add(updateThread);
            // 这里可以添加业务逻辑
            resultList.add(finishThread);
        });
        thread.start();
        // 等待updateThread执行完成,避免和threadName4交叉
        try {
            thread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
    }
}

关键修改点说明

  • 线程安全集合替换:将ArrayList替换为CopyOnWriteArrayList,保证多线程环境下添加元素的安全性,避免并发修改异常或数据丢失
  • 拆分CountDownLatch:使用两个独立的CountDownLatch分别控制前3个线程和threadName4的执行,避免复用导致的计数失效问题
  • 同步updateThread执行:在启动updateThread后调用thread.join(),确保其执行完成后再启动threadName4,符合执行顺序预期
  • 中断处理优化:捕获InterruptedException后重新设置线程中断状态,保证线程中断信号不丢失

内容的提问来源于stack exchange,提问作者priyanka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:35:04