Chapter 16 CompletableFuture : ์์ ์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ
๋น๋๊ธฐ ์์
์ ๋ง๋ค๊ณ ๊ฒฐ๊ณผ ์ป๊ธฐ
๋น๋ธ๋ก ๋์์ผ๋ก ์์ฐ์ฑ ๋์ด๊ธฐ
๋น๋๊ธฐ API ์ค๊ณ์ ๊ตฌํ
๋๊ธฐ API๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์๋นํ๊ธฐ
๋ ๊ฐ ์ด์์ ๋น๋๊ธฐ ์ฐ์ฐ์ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ง๋ค๊ณ ํฉ์น๊ธฐ
๋น๋๊ธฐ ์์
์๋ฃ์ ๋์ํ๊ธฐ
16.1 Future์ ๋จ์ ํ์ฉ
์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ Callable ๊ฐ์ฒด ๋ด๋ถ๋ก ๊ฐ์ผ ๋ค์ ExecutorService์ ์ ์ถ
ExecutorService์์ ์ ๊ณตํ๋ ์ค๋ ๋๊ฐ ์์
์ ์ฒ๋ฆฌํ๋ ๋์ ์ฐ๋ฆฌ ์ค๋ ๋๋ก ๋ค๋ฅธ ์์
์ ๋์์ ์คํ
get ๋ฉ์๋๋ฅผ ํตํ ๊ฒฐ๊ณผ ํ์
์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ด ์์ํ ๋๋์ง ์์ ์ ์์ -> ์ต๋ ํ์์์ ์๊ฐ ์ค์
Future๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋ : ๋น๋๊ธฐ ๊ณ์ฐ์ด ๋๋ฌ๋์ง ํ์ธ, ๊ณ์ฐ์ด ๋๋๊ธธ ๊ธฐ๋ค๋ฆผ, ๊ฒฐ๊ณผ ํ์
์ฌ๋ฌ Future ๊ฒฐ๊ณผ๊ฐ ์์๋ ์์กด์ฑ์ ํํํ๊ธฐ ์ด๋ ค์
Stream๊ณผ ๋น์ทํ๊ฒ ๋๋คํํ์๊ณผ ํ์ดํ๋ผ์ด๋์ ํ์ฉํจ. Future์ CompletableFuture๋ Collection๊ณผ Stream์ ๊ด๊ณ์ ๋น์ ํ ์ ์๋ค.
16.1.2 CompletableFuture๋ก ๋น๋๊ธฐ ์ ํ๋ฆฌ์ผ์ด์
๋ง๋ค๊ธฐ
์ฌ๋ฌ ์จ๋ผ์ธ์์ ์ค ๊ฐ์ฅ ์ ๋ ดํ ๊ฐ๊ฒฉ์ ์ ์ํ๋ ์์ ์ ์ฐพ๋ ์ ํ๋ฆฌ์ผ์ด์
์์
๋ฐฐ์ธ ์ ์๋ ๊ฒ๋ค
๊ณ ๊ฐ์๊ฒ ๋น๋๊ธฐ API๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ
๋๊ธฐ API๋ฅผ ์ฌ์ฉํ ๋ ์ฝ๋๋ฅผ ๋น๋ธ๋ก์ผ๋ก ๋ง๋๋ ๋ฐฉ๋ฒ (๋ ๊ฐ์ ๋น๋๊ธฐ ๋์์ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ง๋ค๊ณ , ๋ ๊ฐ์ ๋์ ๊ฒฐ๊ณผ๋ฅผ ํ๋์ ๋น๋๊ธฐ ๊ณ์ฐ์ผ๋ก ํฉ์น๊ธฐ)
๋น๋๊ธฐ ๋์์ ์๋ฃ์ ๋์ํ๋ ๋ฐฉ๋ฒ
๋๊ธฐ API์ ๋น๋๊ธฐ API
๋๊ธฐ API : ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ค์ ๊ณ์ฐ์ ์๋ฃํ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฐํ๋๋ฉด ๋ค๋ฅธ ๋์์ ์ํ. ๋๊ธฐ API๋ฅผ ์ฌ์ฉํ๋ ์ํฉ์ ๋ธ๋ก ํธ์ถ ์ด๋ผ๊ณ ํจ
๋น๋๊ธฐ API : ๋ฉ์๋๋ ์ฆ์ ๋ฐํ๋๋ฉฐ ๋๋์ง ๋ชปํ ๋๋จธ์ง ์์
์ ๋ค๋ฅธ ์ค๋ ๋์ ํ ๋นํจ. ๋น๋๊ธฐ API๋ฅผ ์ฌ์ฉํ๋ ์ํฉ์ ๋น๋ธ๋ก ํธ์ถ ์ด๋ผ๊ณ ํจ
16.2 ๋น๋๊ธฐ API ๊ตฌํ
์ ํ๋ช
์ ํด๋นํ๋ ๊ฐ๊ฒฉ์ ๋ฐํํ๋ ๋ฉ์๋ ๊ตฌํ(Shop.java)
public class Shop {
// getPrice : ๊ฐ๊ฒฉ ์ ๋ณด๋ฅผ ์ป๋ ๋์์ ๋ค๋ฅธ ์ธ๋ถ ์๋น์ค์ ์ ๊ทผํ๋ ๋ฉ์๋
public double getPrice(String product) {
return calculatePrice(product);
}
public double calculatePrice(String product) {
delay();
return format(random.nextDouble() * product.charAt(0) + product.charAt(1));
}
// delay : ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ ํ๋ด๋ด๋ ๋ฉ์๋
public static void delay() {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
16.2.1 ๋๊ธฐ ๋ฉ์๋๋ฅผ ๋น๋๊ธฐ ๋ฉ์๋๋ก ๋ณํ
์ API๋ฅผ ์ฌ์ฉ์๊ฐ ํธ์ถํ๋ ๊ฒฝ์ฐ ๋น๋๊ธฐ ๋์์ด ์๋ฃ๋ ๋๊น์ง 1์ด ๋์ ๋ธ๋ก๋จ
๋๊ธฐ ๋ฉ์๋ getPrice๋ฅผ ๋น๋๊ธฐ ๋ฉ์๋๋ก ๋ณํํ๊ธฐ(AsyncShop.java)
java.util.concurrent.Future : ๋น๋๊ธฐ ๊ณ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํํํ ์ ์๋ ์ธํฐํ์ด์ค. ๊ณ์ฐ์ด ์๋ฃ๋๋ฉด get ๋ฉ์๋๋ก ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค
public class AsyncShop {
// getPriceAsync : ๋ฉ์๋๊ฐ ํธ์ถ ์ฆ์ ๋ฐํ๋์ด ํธ์ถ์ ์ค๋ ๋๊ฐ ๋ค๋ฅธ ์์
์ ์ํ
public Future<Double> getPriceAsync(String product) {
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
new Thread(() -> {
double price = calculatePrice(product);
futurePrice.complete(price);
}).start();
return futurePrice;
}
}
16.2.2 ์๋ฌ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ
๊ฐ๊ฒฉ์ ๊ณ์ฐํ๋ ๋์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด get ๋ฉ์๋๊ฐ ๋ฐํ๋ ๋๊น์ง ํด๋ผ์ด์ธํธ๊ฐ ๊ธฐ๋ค๋ฆด ์๋ ์์
๋ธ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ ์ํฉ์์ ํ์์์์ ํ์ฉ -> ์๋ฌ ์์ธ์ ์ ์ ์์
completeExceptionally ๋ฉ์๋๋ฅผ ์ด์ฉ -> ์๋ฌ ์์ธ์ ์ ์ ์์
public class AsyncShop {
// completeExceptionally : ๋์ค์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ๋ฐ์ํ ์๋ฌ๋ฅผ ํฌํจ์์ผ Future๋ฅผ ์ข
๋ฃ
public Future<Double> getPriceAsync(String product) {
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
new Thread(() -> {
try {
double price = calculatePrice(product);
futurePrice.complete(price);
} catch (Exception ex) {
futurePrice.completeExceptionally(ex);
}
}).start();
return futurePrice;
}
}
ํฉํ ๋ฆฌ ๋ฉ์๋ supplyAsync๋ก CompletableFuture ๋ง๋ค๊ธฐ
Supplier๋ฅผ ์คํํด์ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ์์ฑ
public class AsyncShop {
public Future<Double> getPriceAsync(String product) {
return CompletableFuture.supplyAsync(() -> calculatePrice(product));
}
}
16.3 ๋น๋ธ๋ก ์ฝ๋ ๋ง๋ค๊ธฐ
16.2์ ๋๊ธฐ API๋ฅผ ์ด์ฉํด์ ์ต์ ๊ฐ๊ฒฉ ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ๋ ์ํฉ์ ๊ฐ์ ํด๋ณด์
์ ํ๋ช
์ ์
๋ ฅํ๋ฉด ์์ ์ด๋ฆ๊ณผ ์ ํ๊ฐ๊ฒฉ ๋ฌธ์์ด ์ ๋ณด๋ฅผ ํฌํจํ๋ List๋ฅผ ๋ฐํํ๋ ๋ฉ์๋ ๊ตฌํ(BestPriceFinder.java)
์์ ์์ ๊ฐ๊ฒฉ์ ๊ฒ์ํ๋ ๋์ ๊ฐ๊ฐ 1์ด์ ๋๊ธฐ์๊ฐ ๋ฐ์
public class BestPriceFinder {
private final List<Shop> shops = Arrays.asList(
new Shop("BestPrice"),
new Shop("LetsSaveBig"),
new Shop("MyFavoriteShop"),
new Shop("BuyItAll"),
public List<String> findPricesSequential(String product) {
return shops.stream()
.map(shop -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)))
.collect(Collectors.toList());
}
}
16.3.1 ๋ณ๋ ฌ ์คํธ๋ฆผ์ผ๋ก ์์ฒญ ๋ณ๋ ฌํํ๊ธฐ
parallelStream์ ์ด์ฉํด์ ์์ฐจ ๊ณ์ฐ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ์ฌ ์ฑ๋ฅ์ ๊ฐ์
16.3.2 CompletableFuture๋ก ๋น๋๊ธฐ ํธ์ถ ๊ตฌํํ๊ธฐ
ํฉํ ๋ฆฌ ๋ฉ์๋ supplyAsync๋ก CompletableFuture ๋ง๋ค๊ธฐ
CompletableFuture์ join ๋ฉ์๋๋ Future ์ธํฐํ์ด์ค์ get ๋ฉ์๋์ ๊ฐ์ ์๋ฏธ๋ก ๋ชจ๋ ๋น๋๊ธฐ ๋์์ด ๋๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
join ์ฌ์ฉ์ ์๋ฌด ์์ธ๋ ๋ฐ์ํ์ง ์์ผ๋ฏ๋ก try/catch ๋ถํ์
public class BestPriceFinder {
public List<String> findPricesFuture(String product) {
List<CompletableFuture<String>> priceFutures =
shops.stream()
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is " + shop.getPrice(product)))
.collect(Collectors.toList());
return priceFutures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
}
์คํธ๋ฆผ ์ฐ์ฐ์ ๊ฒ์ผ๋ฅธ ํน์ฑ์ด ์๊ธฐ ๋๋ฌธ์ ๋ ๊ฐ์ ํ์ดํ๋ผ์ธ์ผ๋ก ์ฐ์ฐ์ ๋๋์ด ์ฒ๋ฆฌ
16.3.3 ๋ ํ์ฅ์ฑ์ด ์ข์ ํด๊ฒฐ ๋ฐฉ๋ฒ
์ค๋ ๋ ๊ฐฏ์๋ฅผ ์ต๋๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊น์ง๋ ๋ณ๋ ฌ ์คํธ๋ฆผ๊ณผ CompletableFuture ๊ฒฐ๊ณผ๊ฐ ๋น์ทํ ์ ์์ผ๋ ๊ทธ ์ด์์ธ ๊ฒฝ์ฐ CompletableFuture ์ฌ์ฉ์ ๋ค์ํ Executor ์ง์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ต์ ํ ๊ฐ๋ฅ
16.3.4 ์ปค์คํ
Executor ์ฌ์ฉํ๊ธฐ
์ ํ๋ฆฌ์ผ์ด์
์ด ์ค์ ๋ก ํ์ํ ์์
๋์ ๊ณ ๋ คํ ํ์์ ๊ด๋ฆฌํ๋ ์ค๋ ๋ ์์ ๋ง๊ฒ Executor ๋ง๋ค๊ธฐ
public class BestPriceFinder {
private final Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(), 100), new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true); // ๋ฐ๋ชฌ ์ค๋ ๋ : ์๋ฐ ํ๋ก๊ทธ๋จ ์ข
๋ฃ์ ๊ฐ์ ๋ก ์คํ ์ข
๋ฃ
return t;
}
});
}
CompletableFuture.supplyAsync(() -> shop.getName() + " price is " + shop.getPrice(product), executor);
๋น๋๊ธฐ ๋์์ ๋ง์ด ์ฌ์ฉํ๋ ์ํฉ์์๋ Executor๋ฅผ ๋ง๋ค์ด CompletableFuture๋ฅผ ํ์ฉํ๋ ๊ฒ์ด ๋ฐ๋์ง
๋ค์์ ์ฐธ๊ณ ํ๋ฉด ์ด๋ค ๋ณ๋ ฌํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ ๊ฒ์ธ์ง ์ ํํ๋๋ฐ ๋์์ด ๋๋ค
I/O๊ฐ ํฌํจ๋์ง ์์ ๊ณ์ฐ ์ค์ฌ์ ๋์์ ์คํํ ๋๋ ์คํธ๋ฆผ ์ธํฐํ์ด์ค ๊ฐ ๊ฐ์ฅ ๊ตฌํํ๊ธฐ ๊ฐ๋จํ๋ฉฐ ํจ์จ์ ์ผ ์ ์๋ค
I/O๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์์
์ ๋ณ๋ ฌ๋ก ์คํํ ๋๋ CompletableFuture ๊ฐ ๋ ๋ง์ ์ ์ฐ์ฑ์ ์ ๊ณตํ๋ค. ์คํธ๋ฆผ์์ I/O๋ฅผ ์ค์ ๋ก ์ธ์ ์ฒ๋ฆฌํ ์ง ์์ธกํ๊ธฐ ์ด๋ ค์ด ๋ฌธ์ ๋ ์๋ค.
16.4 ๋น๋๊ธฐ ์์
ํ์ดํ๋ผ์ธ ๋ง๋ค๊ธฐ
์ ์ธํ์ผ๋ก ์ฌ๋ฌ ๋น๋๊ธฐ ์ฐ์ฐ์ CompletableFuture๋ก ํ์ดํ๋ผ์ธํ ํด๋ณด์
๊ณ์ฝ์ ๋งบ์ ๋ชจ๋ ์์ ์ด ํ๋์ ํ ์ธ ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์์ผ๋ฉฐ(Discount.java)
์์ ์์ getPrice์ ๊ฒฐ๊ณผ ํ์๋ ๋ณ๊ฒฝํ์๋ค(Shop.java)
public class Shop {
public String getPrice(String product) {
double price = calculatePrice(product);
Discount.Code code = Discount.Code.values()[random.nextInt(Discount.Code.values().length)];
return name + ":" + price + ":" + code;
}
public double calculatePrice(String product) {
delay();
return format(random.nextDouble() * product.charAt(0) + product.charAt(1));
}
}
16.4.1 ํ ์ธ ์๋น์ค ๊ตฌํ
์์ ์์ ์ ๊ณตํ ๋ฌธ์์ด ํ์ฑ์ Quote ํด๋์ค๋ก ์บก์ํ(Quote.java)
16.4.2 ํ ์ธ ์๋น์ค ์ฌ์ฉ
Discount๋ ์๊ฒฉ ์๋น์ค์ด๋ฏ๋ก 1์ด์ ์ง์ฐ์ ์ถ๊ฐํจ(delay)
ํ ์ธ ์ ๊ฐ๊ฒฉ์ ์ป์ ํ -> ์์ ์์ ๋ฐํ๋ ๋ฌธ์์ด์ Quote ๊ฐ์ฒด๋ก ๋ณํ ํ -> Discount ์๋น์ค๋ฅผ ์ด์ฉํ์ฌ ํ ์ธ์ ์ ์ฉ
public List<String> findPrices(String product) {
return shops.stream()
.map(shop -> shop.getPrice(product))
.map(Quote::parse)
.map(Discount::applyDiscount)
.collect(Collectors.toList());
}
16.4.3 ๋๊ธฐ ์์
๊ณผ ๋น๋๊ธฐ ์์
์กฐํฉํ๊ธฐ
CompletableFuture ์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ผ๋ก findPrices ๋ฉ์๋๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ฌ๊ตฌํ
public List<String> findPricesFuture(String product) {
List<CompletableFuture<String>> priceFutures =
shops.stream()
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor))
.map(future -> future.thenApply(Quote::parse))
.map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote), executor)))
.collect(Collectors.toList());
return priceFutures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
supplyAsync์ ๋ฎ๋ค ํํ์์ ์ ๋ฌํ์ฌ ๋น๋๊ธฐ์ ์ผ๋ก ์์ ์์ ์ ๋ณด๋ฅผ ์กฐํ
์ฒซ ๋ฒ์งธ ๋ณํ์ ๋ฐํ ๊ฒฐ๊ณผ๋ Stream<CompletableFuture<String>>
๊ฐ CompletableFuture๋ ์์
์ด ๋๋ฌ์ ๋ ํด๋น ์์ ์์ ๋ฐํํ๋ ๋ฌธ์์ด ์ ๋ณด ํฌํจ
์ปค์คํ
executor ์ฌ์ฉ
์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ ๋ฌธ์์ด์ Quote๋ก ๋ณํ -> ์๊ฒฉ ์๋น์ค๋ I/O๊ฐ ์์ผ๋ฏ๋ก ์ง์ฐ ์์ด ๋์ ์ํ ๊ฐ๋ฅ
thenApply ๋ฉ์๋๋ CompletableFuture๊ฐ ๋๋ ๋๊น์ง ๋ธ๋กํ์ง ์์
CompletableFuture๊ฐ ๋์์ ์์ ํ ์๋ฃํ ๋ค์์ thenApply ๋ฉ์๋๋ก ์ ๋ฌ๋ ๋๋ค ํํ์์ ์ ์ฉ
CompletableFuture๋ฅผ ์กฐํฉํ์ฌ ํ ์ธ๋ ๊ฐ๊ฒฉ ๊ณ์ฐํ๊ธฐ
์ฒซ ๋ฒ์งธ map์์ ๋ฐ์ ํ ์ธ์ ๊ฐ๊ฒฉ์ Discount๋ก ํ ์ธ๋ ๊ฐ๊ฒฉ์ ๊ณ์ฐ
์๊ฒฉ ์คํ์ด ํฌํจ๋์ด ๋๊ธฐ์ ์ผ๋ก ์์
์ ์ํํด์ผ ํจ -> ๋๋คํํ์์ผ๋ก supplyAsync์ ์ ๋ฌํ์ฌ ๋ค๋ฅธ CompletableFuture๋ฅผ ๋ฐํ ๊ฐ๋ฅ
๋ ๊ฐ์ง CompletableFuture๋ก ์ด๋ฃจ์ด์ง ์ฐ์์ ์ผ๋ก ์ํ๋๋ ๋น๋๊ธฐ ๋์์ ๋ง๋ค ์ ์๋ค.
์์ ์์ ๊ฐ๊ฒฉ ์ ๋ณด๋ฅผ ์ป์ด์์ Quote๋ก ๋ณํ
๋ณํ๋ Quote๋ฅผ Discount ์๋น์ค๋ก ์ ๋ฌํด์ ํ ์ธ๋ ์ต์ข
๊ฐ๊ฒฉ ํ๋
thenCompose ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ ๋ฒ์งธ ์ฐ์ฐ์ผ๋ก ์ ๋ฌ
16.4.4 ๋
๋ฆฝ CompletableFuture์ ๋น๋
๋ฆฝ CompletableFuture ํฉ์น๊ธฐ
์ค์ ์์๋ ๋
๋ฆฝ์ ์ผ๋ก ์คํ๋ ๋ ๊ฐ์ CompletableFuture ๊ฒฐ๊ณผ๋ฅผ ํฉ์ณ์ผ ํ๋ ์ํฉ์ด ์ข
์ข
๋ฐ์ํจ
thenCombine ๋ฉ์๋๋ BiFunction์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋ฐ์ ๋ ๊ฐ์ CompletableFuture ๊ฒฐ๊ณผ๋ฅผ ํฉ์น๋ค
thenCombineAsync ๋ฉ์๋๋ thenCombine์ Async ๋ฒ์ ์ผ๋ก BiFunction์ด ์ ์ํ๋ ์กฐํฉ ๋์์ด ์ค๋ ๋ ํ๋ก ์ ์ถ๋๋ฉด์ ๋ณ๋์ ํ์คํฌ์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ํ
์ ๋ก(EUR) ๊ฐ๊ฒฉ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ์จ๋ผ์ธ์์ ์์ ๋ฌ๋ฌ(USD) ๊ฐ๊ฒฉ์ผ๋ก ๋ณ๊ฒฝํ์ฌ ๋ณด์ฌ์ฃผ๊ธฐ
16.4.5 Future์ ๋ฆฌํ๋ ์
๊ณผ CompletableFuture์ ๋ฆฌํ๋ ์
Future์ ExecutorService ์ฌ์ฉ์ ์ค๋ ๋ ๋ฐํ ํ์
16.4.6 ํ์์์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ
Future์ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์ฝ์ ๋๋ ๋ฌดํ์ ๊ธฐ๋ค๋ฆฌ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ๋ธ๋ก์ ํ์ง ์๋ ๊ฒ์ด ์ข๋ค
์๋ฐ9์์๋ CompletableFuture์์ ์ ๊ณตํ๋ ๋ฉ์๋๋ฅผ ์ด์ฉํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค
orTimeout : ์ง์ ๋ ์๊ฐ์ด ์ง๋ ํ CompletableFuture๋ฅผ TimeoutException์ผ๋ก ์๋ฃํ๋ฉด์ ๋ ๋ค๋ฅธ CompletableFuture๋ฅผ ๋ฐํ(ScheduledThreadExecutor ํ์ฉ)
completeOnTimeout : ์์
์ด ์๋ฃ๋์ง ์์ผ๋ฉด ๋ฏธ๋ฆฌ ์ง์ ๋ ๊ฐ์ ์ฌ์ฉํ๋๋ก ํจ
16.5 CompletableFuture์ ์ข
๋ฃ์ ๋์ํ๋ ๋ฐฉ๋ฒ
์๊ฒฉ ๋ฉ์๋ ์๋ต์ 1์ด์ ์ง์ฐ์ผ๋ก ๊ณ ์ -> ์ค์ ์์๋ ์ผ๋ง๋ ์ง์ฐ๋ ์ง ์์ธกํ๊ธฐ ์ด๋ ต๋ค
delay๋์ 0.5 ~ 2.5 ์ฌ์ด์ ์ง์ฐ์ ๋ง๋๋ randomDelay ์ฌ์ฉ
16.5.1 ์ต์ ๊ฐ๊ฒฉ ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
๋ฆฌํฉํฐ๋ง
๊ฐ ์์ ์์ ๊ฐ๊ฒฉ ์ ๋ณด๋ฅผ ์ ๊ณตํ ๋๋ง๋ค ์ฆ์ ๋ณด์ฌ์ค ์ ์๋ ์ต์ ๊ฐ๊ฒฉ ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
thenAccept : CompletableFuture๊ฐ ์์ฑํ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ป๊ฒ ์๋นํ ์ง ๋ฏธ๋ฆฌ ์ง์
allOf : CompletableFuture ๋ฐฐ์ด์ ์
๋ ฅ์ผ๋ก ๋ฐ์ ๋ชจ๋ ์๋ฃ๋์์ ๋ CompletableFuture<Void>๋ฅผ ๋ฐํ
anyOf : CompletableFuture ๋ฐฐ์ด์ ์
๋ ฅ์ผ๋ก ๋ฐ์ ํ๋๋ผ๋ ์์
์ด ๋๋ฌ์ ๋ ์๋ฃํ CompletableFuture<Object>๋ฅผ ๋ฐํ
ํ ๊ฐ ์ด์์ ์๊ฒฉ ์ธ๋ถ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ๊ธด ๋์์ ์คํํ ๋๋ ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์ฑ๋ฅ๊ณผ ๋ฐ์์ฑ์ ํฅ์์ํฌ ์ ์๋ค.
์ฐ๋ฆฌ ๊ณ ๊ฐ์๊ฒ ๋น๋๊ธฐ API๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๊ณ ๋ คํด์ผ ํ๋ค. CompletableFuture์ ๊ธฐ๋ฅ์ ์ด์ฉํ๋ฉด ์ฝ๊ฒ ๋น๋๊ธฐ API๋ฅผ ๊ตฌํํ ์ ์๋ค.
CompletableFuture๋ฅผ ์ด์ฉํ ๋ ๋น๋๊ธฐ ํ์คํฌ์์ ๋ฐ์ํ ์๋ฌ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ ๋ฌํ ์ ์๋ค.
๋๊ธฐ API๋ฅผ CompletableFuture๋ก ๊ฐ์ธ์ ๋น๋๊ธฐ์ ์ด๋ก ์๋นํ ์ ์๋ค.
์๋ก ๋
๋ฆฝ์ ์ธ ๋น๋๊ธฐ ๋์์ด๋ ์๋๋ฉด ํ๋์ ๋น๋๊ธฐ ๋์์ด ๋ค๋ฅธ ๋น๋๊ธฐ ๋์์ ๊ฒฐ๊ณผ์ ์์กดํ๋ ์ํฉ์ด๋ ์ฌ๋ฌ ๋น๋๊ธฐ ๋์์ ์กฐ๋ฆฝํ๊ณ ์กฐํฉํ ์ ์๋ค.
CompletableFuture์ ์ฝ๋ฐฑ์ ๋ฑ๋กํด์ Future๊ฐ ๋์์ ๋๋ด๊ณ ๊ฒฐ๊ณผ๋ฅผ ์์ฐํ์ ๋ ์ด๋ค ์ฝ๋๋ฅผ ์คํํ๋๋ก ์ง์ ํ ์ ์๋ค.
CompletableFuture ๋ฆฌ์คํธ์ ๋ชจ๋ ๊ฐ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆด์ง ์๋๋ฉด ์ฒซ ๊ฐ๋ง ์๋ฃ๋๊ธธ ๊ธฐ๋ค๋ฆด์ง ์ ํํ ์ ์๋ค.
์๋ฐ 9์์๋ orTimeout, completeOnTimeout ๋ฉ์๋๋ก CompletableFuture์ ๋น๋๊ธฐ ํ์์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ค.