[자바] 멀티쓰레드 병렬처리 - stream 방식 ExecutorService, Future 방식

2020. 11. 24. 10:26Development/[Java] 자바

728x90

(1) ExecutorService, Future, callable


자바 1.5 버전의 ExecutorService와 callable를 사용한 예시
newSingleThreadExecutor로 하였는데 newFixedThreadPool(숫자) 방식으로 하면 쓰레드 개수를 지정할 수 있다.

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<>();

//리스트, 맵등 반복문으로 작업할 콜렉션
for(String key : map.keySet()) {
            callables.add(() -> {
                
                //원하는 동작 수행

                return "result";
            });

}

//callables 들이 병렬처리된다.
List<Future<String>> futures;
try {
     futures = executorService.invokeAll(callables);
     for(Future<String> future : futures){
         System.out.println("future = " + future.get());
     }
     executorService.shutdown();
 } catch (InterruptedException e) {
     e.printStackTrace();
 } catch (ExecutionException e2) {
     e2.printStackTrace();
 }



(2) stream, ForkJoinPool


자바 1.8에서 등장한 stream 방식으로 진행하게되면 되도록 thread safe, 동시성 보장을 위해 map을 cuncurrentHashMap으로 사용한다.
주의할 점은 아무래도 확실한 믿음(?)이나 디버깅을 하지 않았다면, 각각의 작업이 독립적일 경우에만 아래와 같이 사용하는 편이 좋다.
나의 경우 서버에 특정 정보들을 여러건 insert하는 API에서만 사용하고 있다.
ForkJoinPool의 숫자 4는 쓰레드 개수를 지정한 숫자이다.

final ConcurrentHashMap<String, String> cMap = new ConcurrentHashMap<>();
        
//반복 병렬 작업시, 일부 쓰레드가 오래걸릴때를 대비 (놀고있는 쓰레드가 없도록)하여 ForkJoinPool 사용
ForkJoinPool forkjoinPool = new ForkJoinPool(4);
try {
    forkjoinPool.submit(() -> cMap.keySet().parallelStream().forEach(key -> {

     //원하는 동작수행
     //서버 API를 호출 등..

     })).get();
} catch (InterruptedException e) {
     e.printStackTrace();
} catch (ExecutionException e) {
     e.printStackTrace();
}

728x90