본문 바로가기

Java

CompletableFuture 사용법

CompletableFuture는 Java8에 등장했다. Future와 CompletionStage를 구현했다. 따라서 비동기 연산들을 구성, 결합 실행하고 에러를 처리하는 메소드를 가지고 있다.

간단히 비동기 코드를 실행하고 싶다면, CompletableFuture의 runAsync, supplyAsync 함수를 사용한다. runAsync 는 return 타입이 없는 Runnable을 매개변수로 받고, supplyAsync는 return 타입이 있는 Supplier를 매개변수로 받는다.


CompletableFuture future = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  return "Hello4";
});
//future 가 종료될때까지 block해서 결과를 얻는다.
String result = future.get();

CompletableFuture future2 = CompletableFuture.runAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }

  System.out.println("Hello5");
});
//future 가 종료될때까지 block
future2.get();

 

 

CompletableFuture의 수행 결과를 받아 다시 비동기 코드를 실행 하고 싶은 경우가 있다.

thenApply, thenAccept, thenRun 함수를 이용하면 이를 해결 할 수 있다.

thenApply는 함수를 통해 결과값을 Function 으로 보낼 수 있다.

thenAccept 함수는 return 값이 필요없는 Consumer를 매개변수로 받는다.

thenRun 함수는 결과값, return 값 모두 필요 없다면 Runnable을 매개변수로 받는다.


CompletableFuture future = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  return "Hello6";
});
CompletableFuture future1 = future.thenApply(s -> s + " World1");
CompletableFuture future2 = future.thenAccept(s -> {
  System.out.println(s + " World2");
});
CompletableFuture future3 = future.thenRun(() -> {
  System.out.println("Computation finished.");
});

try {
  String future1Result = future1.get();
  System.out.println(future1Result);
  future2.get();
  future3.get();
} catch(Exception e) {
  e.printStackTrace();
}
//Computation finished.
//Hello6 World2
//Hello6 World1

 

 

CompletableFuture는 여러개의 CompletableFuture를 결합 할 수 있다.

thenCompose 함수를 이용해 CompletableFutre를 순차적으로 연결 할수 있다.

독립적인 2개의 CompletableFuture를 실행시키고 그 결과를 받아서 처리할때는 thenCombine, thenAcceptBoth를 이용한다.


CompletableFuture future = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("1st Future Completed!");
  return "Hello9";
}).thenCompose(s -> CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(1000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("2nd Future Completed!");
  return s + " World!";
}));

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("1st Future Completed!");
  return "Hello10";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(1000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("2nd Future Completed!");
  return " World!";
}), (s1, s2) -> {
  System.out.println("Combined!!");
  return s1 + " " + s2;
});

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(2000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("1st Future Completed!");
  return "Hello11";
}).thenAcceptBoth(CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(1000);
  } catch (Exception e) {
    e.printStackTrace();
  }
  System.out.println("2nd Future Completed!");
  return " World!";
}), (s1, s2) -> {
  System.out.println("Combined!!");
  System.out.println(s1 + " " + s2);
});

 

 

여러 CompletableFuture를 병렬로 실행하고 모든 프로세스가 끝나길 기다렸다가 뭔가를 처리 하고싶다면 allOf 함수를 사용하면 된다.


CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(3000);
  } catch(Exception e) {
    e.printStackTrace();
  }

  System.out.println("future1 Completed!");
  return "Hello";
});

CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(1000);
  } catch(Exception e) {
    e.printStackTrace();
  }

  System.out.println("future2 Completed!");
  return "Beautiful";
});

CompletableFuture future3 = CompletableFuture.supplyAsync(() -> {
  try {
    Thread.sleep(1500);
  } catch(Exception e) {
    e.printStackTrace();
  }

  System.out.println("future3 Completed!");
  return "World";
});

CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3);
System.out.println("CompletableFuture.allOf Test");

try {
  combinedFuture.get();
  System.out.println("All futures Completed!");
} catch(Exception e) {
  e.printStackTrace();
}

 

 

반응형