CompletableFuture#runAsync中的静态集合更新

ser*_*nni 8 java static field updating completable-future

前提条件(通用描述):

1.静态类字段

static List<String> ids = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

2. CompletableFuture#runAsync(Runnable runnable,Executor executor)

static void main(String args[])方法中调用

3.step2添加到调用someCollection内部的元素runAsync

代码段(具体说明):

private static List<String> ids = new ArrayList<>();

public static void main(String[] args) throws ExecutionException, InterruptedException {
    //...
    final List<String> lines = Files.lines(path).collect(Collectors.toList());
    for (List<String> lines : CollectionUtils.split(1024, lines)) {
         CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
             List<User> users = buildUsers();
             populate(users);
         }, executorService);

        futures.add(future);
    }

    private static void populate(List<User> users){
       //...
       ids.add(User.getId);
       //...
    }
}
Run Code Online (Sandbox Code Playgroud)

问题描述:

正如我从并发的角度理解的那样,静态变量不能在线程之间共享,因此数据可能会以某种方式丢失.

它应该改为使用volatile还是合理使用 ConcurrentSkipListSet<String>

Nik*_*ski 2

就线程安全而言,变量是否静态并不重要。重要的是

  1. 线程之间共享状态的可见性。
  2. 当多线程通过类方法使用类对象时的安全性(保留类不变量)。

从可见性的角度来看,您的代码示例很好,因为ids它是静态的,并且将在类创建期间初始化。但是,最好将其标记为finalvolatile取决于ids引用是否可以更改。ArrayList但是,由于设计上没有在多线程环境中保留其不变量,因此违反了安全性。因此,您应该使用专为多线程访问而设计的集合。这个主题应该有助于选择。