如何使用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
相关产品推荐
相关产品推荐

