[Java8] 반복문에서 CompletableFuture 사용하기, CompletableFuture in loop

 

✍️ CompletableFuture in loop

다수의 쓰레드를 만들고, 반복된 작업을 비동기적으로 여러 번 수행하고, 수행 결과를 집계하는 코드를 작성해야 할 때가 있다. 가령 뽑기와 같은 확률 로직이 포함된 서비스의 테스트 코드 작성 시에 이와 같은 니즈가 발생한다. 이때 CompletableFuture를 사용하면 비동기 작업과 콜백 메서드를 매우 쉽게 정의할 수 있다. 

 

아래 코드는 반복문 내부에서 CompletableFutre를 만들어 비동기적으로 작업을 수행해서 결과를 반환하고 콜백 메서드에서 결과를 집계하는 샘플 코드이다.

public class ParallelAdder {

    private List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());

    public void addParallel() {
        ExecutorService executors = Executors.newFixedThreadPool(24);

        // CompletableFuture Function
        Function<Integer, CompletableFuture<Void>> func = i -> CompletableFuture
                .supplyAsync(() -> IntStream.range(1, 10).boxed().collect(Collectors.toList()), executors)
                .thenAccept(l -> synchronizedList.addAll(l));

        // loop 10000 times
        CompletableFuture<Void>[] futures = IntStream.range(0, 10000).boxed()
                .map(func).toArray(CompletableFuture[]::new);

        // wait all
        CompletableFuture.allOf(futures).join();
    }

    public void grouping() {
        Map<Integer, Integer> maps = synchronizedList.stream().
                collect(Collectors.groupingBy(Integer::intValue, Collectors.summingInt(Integer::intValue)));

        maps.entrySet().forEach(System.out::println);
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ParallelAdder parallelAdder = new ParallelAdder();

        parallelAdder.addParallel();
        parallelAdder.grouping(); 
        // 1=10000
        // 2=20000
        // 3=30000
        // 4=40000
        // 5=50000
        // ```
    }
}