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();
}
'Java' 카테고리의 다른 글
Java 람다(Lambda) 표현식, Functional Interface 에 대한 조언 (0) | 2023.08.26 |
---|---|
Java8 이후 람다를 이용하여 Collection 정렬하기 (정렬을 깔끔하게 작성하는 법) (0) | 2023.08.20 |
apache HttpClient, javax.net.ssl.SSLHandshakeException 발생시 대처법 (0) | 2019.12.30 |
for each 문에 대하여 (0) | 2014.03.04 |
다이아몬드 연산자 (Diamond operator, JAVA 7 부터 추가) (0) | 2014.02.26 |