1

想请问大家关于 completablefuture 中参数传递线程安全问题。

 2 years ago
source link: https://www.v2ex.com/t/809923
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  Java

想请问大家关于 completablefuture 中参数传递线程安全问题。

  golangLover · 1 小时 48 分钟前 · 107 次点击

搜了 stackoverflow 似乎没有人提过这个问题,因为我也是迫于公司要初学 java,大家见笑了。

这段代码主要想大家帮忙看看 iterate 函数在 for 循环会不会有线程安全的问题。

主要的问题是:

不肯定 iterate 函数 在 for 循环之中,intA 以及 uuid 会不会有线程安全的问题。 1: 就是 thenApply 里面的 intA 与 supplyAsync 里面的是否一致。 2: 也不肯定这传入的参数 intA 与 uuid, 与 thenApply 里面拿到的会不会都是同一组参数。也就是会不会因为循环而导致 uuid 是拿到较为新的情况,而 intA 比较旧?导致计算结果不合理。

我原本想把结果 print 出来测试一下,但是又无从下手,因为这如果真的有线程安全问题也不是 debugger 能看的出来。

先感谢大家的赐教。谢谢

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Test {
    public static void main(String[] args) {
        new Test().run();
    }

    private void run() {
        List<Integer> list = IntStream.range(1,10000).boxed().collect(Collectors.toList());

        List<CompletableFuture<Integer>> cfList = new ArrayList<>();

        for (Integer intA: list) {
            String uuid = UUID.randomUUID().toString();
            CompletableFuture<Integer> future = this.iterate(intA,uuid);
            cfList.add(future);
        }

        CompletableFuture<List<Integer>> resultCf = this.allOf(cfList);
        resultCf.join();
    }

    private  CompletableFuture<Integer> iterate(Integer intA, String uuid) {

        return CompletableFuture.supplyAsync(()->{
//            假设需要用到第一个参数,然后返回
            return intA+2;
        }).thenApply((req)->{
            return intA+5;
        }).thenApply((value)->{
//            假设这个耗时操作要用到第一个参数以及第二个参数。
//            不肯定 在 for 循环之中,intA 以及 uuid 会不会有线程安全的问题。
//            1: 就是 thenApply 里面的 intA 与 supplyAsync 里面的是否一致。
//            2: 也不肯定这传入的参数 intA 与 uuid, 与 thenApply 里面拿到的会不会都是同一组参数。
//            也就是会不会因为循环而导致 uuid 是拿到较为新的情况,而 intA 比较旧?导致计算结果不合理。
            System.out.println(uuid);
            return 3+value;
        });
    }

//     等待 list 完毕
    private  <T> CompletableFuture<List<T>> allOf(List<CompletableFuture<T>> futuresList) {
        CompletableFuture<Void> allFuturesResult =
                CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[0]));
        return allFuturesResult.thenApply(v ->
                futuresList.stream().
                        map(CompletableFuture::join).
                        collect(Collectors.toList())
        );
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK