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

Spring多线程场景下如何避免返回更新中的不完整List?

问题描述

我有一个名为people的List,每72小时通过Spring调度注解更新一次——更新逻辑是调用外部API获取JSON,计算后生成新列表替换原people列表,没有其他更新场景,也没用到数据库。

我的Controller接口返回这个列表的代码如下:

@GetMapping 
public ResponseEntity<List<String>> getPeople() { 
    List<String> people = peopleService.getPeople(); 
    return ResponseEntity.ok(people); 
}

我担心在Service更新列表的同时,Controller的请求会拿到不完整的列表,比如出现这样的情况:"你开始读取myList,此时它指向List#1;读取过程中发生更新,myList被设置为List#2(即新列表),而你仍在读取List#1。"

我自己想了个方案,用一个boolean变量isProcessing来控制更新与读取的时机:

isProcessing = true; 
people = getPeople(); 
isProcessing = false;

请问这个方案可行吗?有没有其他更好的解决方法?谢谢。


问题解答

首先得说,你的isProcessing方案其实不太靠谱,咱们来掰扯清楚:
这个boolean变量本身就存在线程安全问题——如果不加volatile修饰,其他线程可能看不到它的最新值;就算加了volatile,也会出现"刚检查完isProcessing为false、准备读取列表,更新线程就把isProcessing设为true"的时间间隙,根本拦不住你担心的场景,反而多了不必要的复杂度。

不过你的场景其实很清晰:只有定时全量替换列表,没有在原列表内增删改的操作,这种情况完全有更简单优雅的线程安全方案:

最推荐:用volatile修饰列表引用

因为你更新时是直接把people指向一个全新的完整列表,不是在旧列表里修改内容。只要给people变量加上volatile关键字,就能保证所有线程看到的都是最新的列表引用:

// Service中的成员变量
private volatile List<String> people = new ArrayList<>();

// 带Spring调度注解的定时更新方法
public void updatePeople() {
    // 先在局部变量里生成好完整的新列表,这一步完全不影响旧列表
    List<String> newPeople = fetchExternalDataAndProcess();
    // 原子性地替换引用,这一步是线程安全的
    people = newPeople;
}

public List<String> getPeople() {
    return people;
}

这样做的好处:

  • 读取请求完全无锁,性能拉满;
  • 线程要么拿到完整的旧列表,要么拿到完整的新列表,绝对不会读到半更新的状态——因为引用替换是原子操作,不会被打断。

备选:用AtomicReference封装列表

如果你觉得volatile不够直观,用AtomicReference来封装列表引用也可以,本质和上面的方法一致,只是语义更明确:

private AtomicReference<List<String>> peopleRef = new AtomicReference<>(new ArrayList<>());

public void updatePeople() {
    List<String> newPeople = fetchExternalDataAndProcess();
    peopleRef.set(newPeople);
}

public List<String> getPeople() {
    return peopleRef.get();
}

不推荐的方案:CopyOnWriteArrayList

虽然它也是线程安全的,但它是针对"频繁读、偶尔在列表内部修改"的场景设计的,每次修改都会复制整个列表。而你是直接替换整个列表,用它反而有点浪费性能,所以优先选前两种方法。

回到你的问题:那个isProcessing的方案真的没必要,反而容易引入新的线程安全问题。用volatile修饰列表引用就完美解决你的顾虑了。


内容的提问来源于stack exchange,提问作者T.S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:19:56