CompletableFuture

구름코딩·2020년 10월 10일
1

java8 _ 더 자바

목록 보기
17/23
post-custom-banner

기존 Future

ExecutorService executorService = Executors.newFixedThreadPool(4);
Future<String> future = executorService.submit(() -> "hello");
String s = future.get();
System.out.println(s);

executorService.shutdown(); <-- 쓰레드를 명시적으로 닫아주지 않으면 계속 열려있다 (프로세스가 종료되지 않음)

CompletableFuture

  • 자바에서 비동기(Asynchronous) 프로그래밍을 가능하게 하는 인터페이스
  • Future를 사용해도 가능하지만 역부족했다
  • Fork/Join 프레임워크 사용 (기본 쓰레드 풀 : ForkJoinPool.commonPool())
    • ExecutorService의 구현체로 손쉽게 멀티 프로세서를 활용할 수 있게끔 도와준다
//따로 쓰레드풀을 선언하지 않아도 실행이 되며, 쓰레드를 명시적으로 닫아주지 않아도 된다
CompletableFuture<String> future = new CompletableFuture<>();
future.complete("woonsik");
System.out.println(future.get());

CompletableFuture<String> future1 = CompletableFuture.completedFuture("woonsik");
System.out.println(future1.get());

개선된점

  • Future에서는 블로킹 코드(get())을 사용하지 않는이상 작업이 끝났을 때, 콜백을 실행할 수 없었다
  • 여러개의 Future를 조합할수 있게 되었다 (event 정보를 가져와서 event 참석 목록 가져오기 등)
  • 예외처리를 위한 API를 제공한다

비동기로 작업 실행

리턴값이 없는 경우 : runAsync()

CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
    System.out.println("HI woonsik " + Thread.currentThread().getName());
});
future2.get();

리턴값이 있는 경우 : supplyAsync()

//반환값이 있는 경우 supplyAsync()
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
    return ("Hi woonsik " + Thread.currentThread().getName());
});
String s = future3.get();
System.out.println(s);

콜백 제공

  • 리턴값을 받았을때 비동기(Asynchronous)적으로 해당하는 콜백을 했으면 할때
  • 콜백 함수 ("called at the back" of the other function)
    • 다른 함수의 인자로써 이용되는 함수
    • 어떤 이벤트에 의해 호출되어지는 함수
  • 콜백 : 어떤 일을 다른 객체에게 맡기고 그일이 끝나서 다시 부를때 까지 나의 일을 하는 것

thenApply(Function)

  • 넘겨받은 return값에 대해서 처리를 하고 해당값을 다시 return한다
CompletableFuture<String> future4 = CompletableFuture.supplyAsync(()->{
    System.out.println("hi woonsik "+ Thread.currentThread().getName());
    return "hi woonsik";
}).thenApply(string -> {
    System.out.println(Thread.currentThread().getName());
    return string.toUpperCase();
});
//get()을 호출하기 전에 정의하는것이 불가능했지만 CompletableFuture를 사용함으로서 callBack이 가능하다
System.out.println(future4.get());

thenAccept(Consumer)

  • Consumer가 인자로 온다. return값을 받아서 처리만 하고 따로 return값은 없다
CompletableFuture<Void> future5 = CompletableFuture.supplyAsync(()->{
    System.out.println("hi woonsik"+Thread.currentThread().getName());
    return "hi woonsik";
}).thenAccept(string2 -> {
    System.out.println(string2.toUpperCase()+ " " + Thread.currentThread().getName());
});
future5.get();

thenRun(Runnable)

  • Runnable이 인자로 온다. return값을 받지도않고 반환하지도 않는다, 추가적인 행동만 한다
CompletableFuture<Void> future6 = CompletableFuture.supplyAsync(() -> {
    System.out.println("Hi woonsik "+ Thread.currentThread().getName());
    return "hi woonsik";
}).thenRun(()->{
    System.out.println("more only action");
});
future6.get();

CompletableFuture에 원하는 쓰레드풀 사용하기

원하는 Executor(쓰레드풀)을 사용해서 실행 할 수도 있다. 두번째 인자로 Executor 전달
(기본은 ForkJoinPool.commonPool()이다)

ExecutorService executorService = Executors.newFixedThreadPool(4);
CompletableFuture<Void> future7 = CompletableFuture.runAsync(() -> {
    System.out.println("hi woonsik " + Thread.currentThread().getName());
    return;
}, executorService);
future7.get();
executorService.shutdown(); //<- 쓰레드를 닫아줘야 한다
profile
내꿈은 숲속의잠자는공주
post-custom-banner

0개의 댓글