Java

CompletableFuture 사용법

purepleya 2020. 2. 7. 00:15

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();
}

 

 

반응형