[Java] CompletableFuture๋ก ๋น๋๊ธฐ ๋ฐ ๋ณ๋ ฌ ์ฒ๋ฆฌํ๊ธฐ
Future vs CompletableFuture
Future์ CompletableFuture๋ ๋ชจ๋ Java์์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๊ธฐ ์ํ ๋๊ตฌ์ ๋๋ค. Java 5์์ ๋์ ๋ Future๋ ๋น๋๊ธฐ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํํํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, Java 8์์ ๋์ ๋ CompletableFuture๋ Future๋ฅผ ํ์ฅํ์ฌ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
CompletableFuture์ Future์ฐจ์ด๋ ๋ฌด์์ผ๊น์? Future์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ด๋ฒ ํฌ์คํ ์ ์ฃผ์ ์์ ๋ฒ์ด๋ ๊ฒ ๊ฐ์ ๊ฐ๋จํ๊ฒ CompletableFuture์์ ์ฐจ์ด์ ๋ง ๋น๊ตํด ๋ณด์์ต๋๋ค.
Blocking vs Non-Blocking
- Future๋ get() ๋ฉ์๋๋ฅผ ํตํด ๋น๋๊ธฐ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค. ํ์ง๋ง ์ด ๋ฉ์๋๋ ์ฐ์ฐ์ด ์๋ฃ๋ ๋๊น์ง ํ์ฌ ์ค๋ ๋๋ฅผ ์ฐจ๋จ(blocking)ํฉ๋๋ค. ์ฆ, ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ํ์ฌ ์ค๋ ๋๋ ๋๊ธฐ ์ํ์ ๋จธ๋ฌด๋ฅด๊ฒ ๋ฉ๋๋ค.
- ๋ฐ๋ฉด์, CompletableFuture๋ ์ฐ์ฐ์ด ์๋ฃ๋๋ฉด ์๋์ผ๋ก ์ฝ๋ฐฑ ํจ์๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์์๋ ๋ค๋ฅธ ์์ ์ ๊ณ์ ์งํํ ์ ์์ต๋๋ค. ์ด๋ Non-Blocking ๋ฐฉ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
๋จ์ผ ์ฐ์ฐ vs ์ฐ์ฐ์ ์กฐํฉ
- Future๋ ๋จ์ผ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ง์ ํํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
- ๋ฐ๋ฉด์, CompletableFuture๋ thenCompose(), thenCombine() ๋ฑ์ ๋ฉ์๋๋ฅผ ํตํด ์ฌ๋ฌ ๋น๋๊ธฐ ์ฐ์ฐ์ ์กฐํฉํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํํํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋์ฑ ๋ณต์กํ ๋น๋๊ธฐ ๋ก์ง์ ๊ตฌํํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, ๋ณต์กํ ๋น๋๊ธฐ ๋ก์ง์ ๊ตฌํํ๊ฑฐ๋, ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋์ค์ ๋ค๋ฅธ ์์ ์ ์งํํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ CompletableFuture๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ์ฉํฉ๋๋ค.
CompletableFuture๋?
Java 8์์ ๋์ ๋ CompletableFuture๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ ํด๋์ค๋ก, Future์ CompletionStage ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ๋ณด๋ค ๊ฐํธํ๊ณ ํจ๊ณผ์ ์ผ๋ก ์ํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
์ฃผ์ ํน์ง
- ์ฌ๋ฌ ๋น๋๊ธฐ ์์
๋์์ ์ํ ๊ฐ๋ฅ
- CompletableFuture๋ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๋์์ ์ํํ๋ ๊ฒ์ ์ง์ํฉ๋๋ค. ์ด๋ ํนํ IO ์์ ์ด๋ ๋คํธ์ํฌ ํต์ ๊ณผ ๊ฐ์ด ๋๊ธฐ ์๊ฐ์ด ๋ฐ์ํ ์ ์๋ ์์ ์์ ๋งค์ฐ ํจ์จ์ ์ธ๋ฐ ๊ฐ ์์ ์ด ์๋ฃ๋๋ ์์ ์ ๋ฐ๋ผ ์ถ๊ฐ์ ์ธ ์์ ์ ์ํํ๊ฑฐ๋, ๋ชจ๋ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ ๋ฑ์ ๋ณต์กํ ํ๋ฆ ์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
- ์์
์ ๋ณํฉ, ์ทจ์, ์๋ฌ ์ฒ๋ฆฌ ๋ฑ์ ๊ธฐ๋ฅ ์ ๊ณต
- CompletableFuture๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ค๋ฅธ ๋น๋๊ธฐ ์์ ์ ์ ๋ ฅ์ผ๋ก ์ฌ์ฉํ๊ฑฐ๋, ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์์ ์ฒ๋ฆฌํ๋ ๋ฑ์ ๊ณ ๊ธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. ๋ํ, ํ์ํ ๊ฒฝ์ฐ ๋น๋๊ธฐ ์์ ์ ์ทจ์ํ๊ฑฐ๋, ์์ ์ค ๋ฐ์ํ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค.
- ์์ธ ์ฒ๋ฆฌ์ ๋ํ ์ง์์ด ํ์
- CompletableFuture๋ ๋น๋๊ธฐ ์์ ์ค์ ๋ฐ์ํ ์์ธ๋ฅผ ๊ฐ์งํ๊ณ ์ ์ ํ ์ฒ๋ฆฌํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์์ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ ์ํฉ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๋น๋๊ธฐ ์์ ์์
supplyAsync, runAsync๋ ๋น๋๊ธฐ ์์ ์ ์์ํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋๋ค.
1. supplyAsync()
supplyAsync() ๋ฉ์๋๋ Supplier ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ธ์๋ก ๋ฐ์, ํด๋น ํจ์ํ ์ธํฐํ์ด์ค์ get() ๋ฉ์๋๊ฐ ์คํํ๋ ์์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ํํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ CompletableFuture ๊ฐ์ฒด๋ก ๊ฐ์ธ์ ๋ฐํํ๋๋ฐ, ์ด CompletableFuture ๊ฐ์ฒด๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ฉฐ ์์ ์ ์ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค.
์๋ ์ฝ๋๋ supplyAsync()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
String result = "Hello, World!";
return result;
});
2. runAsync()
runAsync() ๋ฉ์๋๋ Runnable ์ธํฐํ์ด์ค๋ฅผ ์ธ์๋ก ๋ฐ์, ํด๋น ์ธํฐํ์ด์ค์ run() ๋ฉ์๋๊ฐ ์คํํ๋ ์์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ํํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ง ์์ผ๋ฏ๋ก, ๋ฐํ ํ์ ์ CompletableFuture<Void>๊ฐ ๋ฉ๋๋ค.
์๋ ์ฝ๋๋ runAsync()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
System.out.println("Hello, World!");
});
์ด์ฒ๋ผ, supplyAsync()์ runAsync() ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง๋ง, ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ์ฌ์ฉํ๋ ์ธํฐํ์ด์ค์ ๋ฐํ ํ์ ์ด ๋ค๋ฆ ๋๋ค.
์ ๋ฆฌ
๋น๋๊ธฐ ๊ฒฐ๊ณผ ์กฐ์
thenApply[Async], thenAccept[Async], thenRun[Async]์ CompletableFuture ํด๋์ค์์ ์ฐ์์ ์ธ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ค์ ๋๋ค.
1. thenApply / thenApplyAsync
thenApply[Async] ๋ฉ์๋๋ ๋ชจ๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์๋ก์ด ์ฐ์ฐ์ ์ํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ CompletableFuture๋ก ๋ฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello";
}).thenApply(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ๋ค๋ฅธ ์ฐ์ฐ ์ํ
return result + ", World!";
});
๊ฒฐ๊ณผ: "Hello World!"
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด "Hello, World!"๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ thenApply ๋ฉ์๋๋ ์ด์ ์์ ์ด ์๋ฃ๋ ํ์ ํจ์๋ฅผ ๋์ผํ ์ค๋ ๋์์ ์คํํ๋ฉฐ, ์ด์ ์์ ๊ณผ ๋๊ธฐ์ ์ผ๋ก ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๋๋ค.
๋ฐ๋ฉด, thenApplyAsync ๋ฉ์๋๋ ์ด์ ์์ ์ด ์๋ฃ๋ ํ์ ํจ์๋ฅผ ์๋ก์ด ์ค๋ ๋ ๋๋ ์ค๋ ๋ ํ์์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํฉ๋๋ค. ์ด ๋ฐฉ์์ ์ด์ ์์ ๊ณผ ๋ ๋ฆฝ์ ์ผ๋ก ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๋ฉฐ, ์์ ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello";
}).thenApplyAsync(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ๋ค๋ฅธ ์ฐ์ฐ ์ํ
return result + ", World!";
});
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ง์ฐฌ๊ฐ์ง๋ก "Hello, World!"๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ์ด์ฒ๋ผ thenApplyAsync๋ฅผ ์ฌ์ฉํ๋ฉด, ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์์ ์ ์ํํ๋ฉด์๋ ๋ฉ์ธ ์ค๋ ๋๊ฐ ๋ธ๋กํน๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello";
}).thenApplyAsync(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ๋ค๋ฅธ ์ฐ์ฐ ์ํ
return result + ", World!";
});
System.out.println("Continuing with other work...");
์์ ์ฝ๋์์๋ thenApplyAsync๊ฐ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์์๋ ๋ฉ์ธ ์ค๋ ๋๋ "Continuing with other work..."๋ผ๋ ๋ฌธ์ฅ์ ์ถ๋ ฅํ๋ ๋ฑ์ ๋ค๋ฅธ ์์ ์ ๊ณ์ํด์ ์ํํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, thenApply์ thenApplyAsync๋ ๋ชจ๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์์ ์ ์ํํ์ง๋ง, ๋์ ๋ฐฉ์์๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค. thenApply๋ ๋๊ธฐ์ ์ผ๋ก ๊ฐ์ ์ค๋ ๋์์ ์์ ์ด ์ด๋ฃจ์ด์ง๋ ๋ฐ๋ฉด, thenApplyAsync๋ ๋น๋๊ธฐ์ ์ผ๋ก ๋ณ๋์ ์ค๋ ๋์์ ์์ ์ด ์ํ๋ฉ๋๋ค.
2. thenAccept / thenAcceptAsync
์ด์ ๋จ๊ณ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ํด๋น ๊ฒฐ๊ณผ๋ฅผ ์๋นํ๋ ์์ ์ ์ํํ๊ณ , ๋ฐํ๊ฐ์ด ์์ต๋๋ค. ์๋ ์ฝ๋๋ supplyAsync๋ก ๋น๋๊ธฐ ์์ ์ ์์ํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ thenAccept๋ก ์๋นํ๋ ์์ ๋๋ค.
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello, World!";
}).thenAccept(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ์๋น๋ง ํจ
System.out.println(result);
});
๊ฒฐ๊ณผ: "Hello World!"
์คํํ๋ฉด "Hello World!"๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ฉฐ, ๋ฐํ๊ฐ์ด ์์ผ๋ฏ๋ก CompletableFuture<Void>๊ฐ ์์ฑ๋ฉ๋๋ค. thenAcceptAsync ๋ฉ์๋๋ ๋ง์ฐฌ๊ฐ์ง๋ก thenAccept์ ๋์ผํ ์์ ์ ์ํํ์ง๋ง, ๋ณ๋์ ์ค๋ ๋์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฐ์ฐ์ ์ํํฉ๋๋ค.
3. thenRun / thenRunAsync
์ด์ ๋จ๊ณ์ ๊ฒฐ๊ณผ์ ์๊ด์์ด ํน์ ์์ ์ ์คํํฉ๋๋ค. ์๋ ์ฝ๋๋ supplyAsync๋ก ๋น๋๊ธฐ ์์ ์ ์์ํ๊ณ , ๊ทธ ์์ ์ด ๋๋๋ฉด ๊ฒฐ๊ณผ์ ์๊ด์์ด "Finished!"๋ผ๋ ๋ฌธ์์ด์ ์ถ๋ ฅํ๋ ์์ ๋๋ค.
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello, World!";
}).thenRun(() -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ์ ์๊ด์์ด ์คํํ ์์
System.out.println("Finished!");
});
๊ฒฐ๊ณผ: "Finished!"
์ด๋ฅผ ์คํํ๋ฉด "Finished!"๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ฉฐ, ๋ฐํ๊ฐ์ด ์์ผ๋ฏ๋ก CompletableFuture<Void>๊ฐ ์์ฑ๋ฉ๋๋ค. thenRunAsync ๋ฉ์๋๋ thenRun ๋ฉ์๋์ ๊ฐ์ ์์ ์ ์ํํ์ง๋ง, ๋ณ๋์ ์ค๋ ๋์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฐ์ฐ์ ์ํํฉ๋๋ค.
์ ๋ฆฌ
๋น๋๊ธฐ ์์ ์กฐํฉ
๋น๋๊ธฐ ์์ ์ ์กฐํฉํ๋ ๋ฐฉ๋ฒ์๋ thenCompose[Async], thenCombine[Async], allOf(), anyOf() ๋ฑ์ ๋ฉ์๋๊ฐ ์์ต๋๋ค.
1. thenCompose / thenComposeAsync
thenCompose()์ thenComposeAsync() ๋ฉ์๋๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ด์ฉํ์ฌ ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๋ฉ์๋๋ค์ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ Function์ ์ธ์๋ก ๋ฐ์, ์๋ก์ด CompletableFuture๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค.
๋ค์์ thenCompose()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello";
}).thenCompose(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํ
return CompletableFuture.supplyAsync(() -> {
return result + ", World!";
});
});
์ ์ฝ๋์์ thenCompose() ๋ฉ์๋๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ์ธ "Hello" ๋ฌธ์์ด์ ์ธ์๋ก ๋ฐ์, ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํํฉ๋๋ค. ์ด ์๋ก์ด CompletableFuture๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ์ ", World!"๋ฅผ ์ถ๊ฐํ์ฌ ์๋ก์ด ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
thenComposeAsync() ๋ฉ์๋๋ thenCompose()์ ๋น์ทํ์ง๋ง, ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ํจ์๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ด์ ์์ ๊ณผ ๋ ๋ฆฝ์ ์ผ๋ก ์๋ก์ด ์์ ์ ์ํํ ์ ์์ด, ์์ ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
๋ค์์ thenComposeAsync()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์์
return "Hello";
}).thenComposeAsync(result -> {
// ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํ
return CompletableFuture.supplyAsync(() -> {
return result + ", World!";
});
});
์ ์ฝ๋์์ thenComposeAsync() ๋ฉ์๋๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ์ธ "Hello" ๋ฌธ์์ด์ ์ธ์๋ก ๋ฐ์, ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ํจ์๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์๋ก์ด CompletableFuture๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ์ ", World!"๋ฅผ ์ถ๊ฐํ์ฌ ์๋ก์ด ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
๋ฐ๋ผ์ thenCompose()์ thenComposeAsync() ๋ฉ์๋๋ ์ด์ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ๋น๋๊ธฐ ์์
์ ์์ฑํ๊ณ ์คํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๋์ ์ฐจ์ด์ ์ ์๋ก์ด ๋น๋๊ธฐ ์์
์ ๋๊ธฐ์ ์ผ๋ก ์คํํ๋๋(thenCompose()) ์๋๋ฉด ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ๋๋(thenComposeAsync())์ ์์ต๋๋ค.
thenCompose[Async] vs thenApply[Async]
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์ ๋น๋๊ธฐ ์์ ์กฐํฉ์ธ thenCompose[Async]์ ๋น๋๊ธฐ ๊ฒฐ๊ณผ ์กฐ์์ธ thenApply[Async]๊ฐ ๋น์ทํ๋ค๊ณ ๋๋ ์๋ ์๋๋ฐ, ์ฃผ์ ์ฐจ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- thenApply()๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ํน์ ์ฐ์ฐ์ ์ํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋ฐ๋ฉด, thenCompose[Async]๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ฉํ์ฌ ์๋ก์ด ๋น๋๊ธฐ ์์ ์ ์์ฑํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
- ์ฆ, thenApply()๋ ์ฃผ๋ก ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณํํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, thenCompose[Async]๋ ์ด์ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก ์๋ก์ด ๋น๋๊ธฐ ์์ ์ ์์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
2. thenCombine / thenCombineAsync
thenCombine[Async] ๋ฉ์๋๋ ๋ ๊ฐ์ CompletableFuture๊ฐ ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ, ๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ด์ฉํ์ฌ ์๋ก์ด ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. thenCombine[Async]๋ ๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ BiFunction์ ์ธ์๋ก ๋ฐ์, ์๋ก์ด ๊ฐ์ ๊ณ์ฐํ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค.
๋ค์์ thenCombine()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<String> hello = CompletableFuture.supplyAsync(() -> {
return "Hello";
});
CompletableFuture<String> world = CompletableFuture.supplyAsync(() -> {
return "World";
});
CompletableFuture<String> future = hello.thenCombine(world, (h, w) -> {
return h + ", " + w + "!";
});
์ ์ฝ๋์์ thenCombine() ๋ฉ์๋๋ ๋ ๊ฐ์ CompletableFuture, hello์ world๊ฐ ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ๋ ์์ ์ด ๋ชจ๋ ์๋ฃ๋๋ฉด, thenCombine() ๋ฉ์๋๋ ๋ ์์ ์ ๊ฒฐ๊ณผ์ธ "Hello"์ "World"๋ฅผ ์ธ์๋ก ๋ฐ์, ์๋ก์ด ๊ฐ์ ๊ณ์ฐํ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค. ์ด ์๋ก์ด ๊ฐ์ "Hello, World!"์ ๋๋ค.
์ง๊ธ๊น์ง์ ๋ง์ฐฌ๊ฐ์ง๋ก thenCombineAsync() ๋ฉ์๋๋ thenCombine()์ ๋น์ทํ์ง๋ง, ์๋ก์ด ๊ฐ์ ๊ณ์ฐํ๋ ํจ์๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ๋ฉฐ, ๋ ์์
๊ณผ ๋
๋ฆฝ์ ์ผ๋ก ์๋ก์ด ๊ฐ์ ๊ณ์ฐํ ์ ์์ด, ์์
์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
thenCompose[Async] vs thenCombine[Async]
์ฌ๊ธฐ์ thenCompose[Async]์ thenCombine[Async]์ ์ฃผ์ ์ฐจ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- thenCompose[Async]๋ ํ๋์ CompletableFuture์ ๊ฒฐ๊ณผ๋ฅผ ์ด์ฉํ์ฌ ์๋ก์ด CompletableFuture๋ฅผ ์์ฑํ๊ณ ์คํํฉ๋๋ค.
- ์ฆ, thenCompose[Async]๋ ์ฒด์ธ ํํ์ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, thenCombine[Async]๋ ๋ ๊ฐ์ ๋ ๋ฆฝ์ ์ธ ๋น๋๊ธฐ ์์ ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํฉ์น๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
3. allOf()
allOf()๋ฉ์๋๋ ์ฌ๋ฌ ๊ฐ์ CompletableFuture๋ฅผ ๋ฐฐ์ด๋ก ๋ฐ์, ๋ชจ๋ ๋น๋๊ธฐ ์์ ์ด ๋์์ ์คํ๋๋๋ก ํฉ๋๋ค. ๋ํ ๋ชจ๋ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ, ๋ชจ๋ ์์ ์ด ์๋ฃ๋๋ฉด CompletableFuture<Void>๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ชจ๋ ๋น๋๊ธฐ ์์ ์ ์๋ฃ๋ฅผ ์๋ฆด ์ ์์ต๋๋ค.
CompletableFuture<String> hello = CompletableFuture.supplyAsync(() -> {
return "Hello";
});
CompletableFuture<String> world = CompletableFuture.supplyAsync(() -> {
return "World";
});
CompletableFuture<Void> future = CompletableFuture.allOf(hello, world);
์ ์ฝ๋์์ allOf() ๋ฉ์๋๋ hello์ world ๋ CompletableFuture๋ฅผ ๋ฐฐ์ด๋ก ๋ฐ์, ๋ ์์ ์ด ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ๋ ์์ ์ด ๋ชจ๋ ์๋ฃ๋๋ฉด, allOf() ๋ฉ์๋๋ CompletableFuture<Void>๋ฅผ ๋ฐํํ์ฌ ๋ชจ๋ ์์ ์ ์๋ฃ๋ฅผ ์๋ฆฝ๋๋ค.
allOf() ๋ฉ์๋๋ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ด ๋์์ ์ํ๋์ด์ผ ํ๊ณ , ๋ชจ๋ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ ์ํฉ์์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์ด๋ฐ ํน์ฑ ๋๋ถ์ allOf() ๋ฉ์๋๋ ์ฃผ๋ก ๋ณ๋ ฌ ์ฒ๋ฆฌ ์์ ์ ์ฌ์ฉ๋๋๋ฐ, ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๋์์ ์ํํ๊ณ ๋ชจ๋ ์์ ์ด ์๋ฃ๋๋ ์์ ์ ์์์ผ ํ ๋ allOf() ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ํจ์จ์ ์ธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํฉ๋๋ค.
4. anyOf()
anyOf() ๋ฉ์๋๋ ์ฌ๋ฌ ๊ฐ์ CompletableFuture ์ค์์ ๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ํ CompletableFuture<Object>๋ฅผ ๋ฐํํ๋ฉฐ, ๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์๋ฆฌ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๋ค์์ anyOf()๋ฅผ ์ฌ์ฉํ ์์ ๋๋ค.
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
return "cf1";
});
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {
return "cf2";
});
CompletableFuture<Object> future = CompletableFuture.anyOf(cf1, cf2);
์ ์ฝ๋์์ anyOf() ๋ฉ์๋๋ cf1๊ณผ cf2 ๋ ๊ฐ์ CompletableFuture ์ค์์ ๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ ์์ ์ค ์ด๋ ๊ฒ์ด ๋จผ์ ์๋ฃ๋๋๋ผ๋, anyOf() ๋ฉ์๋๋ CompletableFuture<Object>๋ฅผ ๋ฐํํ์ฌ ๊ฐ์ฅ ๋จผ์ ์๋ฃ๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์๋ฆฝ๋๋ค.
anyOf() ๋ฉ์๋๋ ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ค์์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์๋ฃ๋๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ณ ์ ํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ฉ๋๋ค. ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๋์์ ์ํํ๊ณ , ๊ทธ์ค ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์๋ฃ๋๋ ๊ฒฐ๊ณผ๋ง ํ์ํ ์ํฉ์์ anyOf() ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ํจ์จ์ ์ธ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ ๋ฆฌ
๋น๋๊ธฐ ์์ธ์ฒ๋ฆฌ
1. handle[Async]
handle[Async] ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋, ์์ ์ค ๋ฐ์ํ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ญํ ์ ํฉ๋๋ค. ์์ ์ด ์ ์์ ์ผ๋ก ์๋ฃ๋๋ฉด ๊ฒฐ๊ด๊ฐ์ ๋ฐํํ๊ณ , ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์์ธ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. handle[Async]์ ๊ฒฐ๊ณผ๊ฐ ๋๋ ์์ธ๋ฅผ ์ธ์๋ก ๋ฐ์ ์ฒ๋ฆฌํ ํ, ์๋ก์ด ๊ฐ์ ๋ฐํํฉ๋๋ค.
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Exception!");
}
return 100;
}).handle((res, ex) -> {
if (ex != null) {
System.out.println("์์ธ ๋ฐ์: " + ex);
return -1;
}
return res;
});
์ด ์ฝ๋์์ CompletableFuture.supplyAsync() ๋ฉ์๋๋ฅผ ํตํด ๋น๋๊ธฐ ์์ ์ ์์ํฉ๋๋ค. ์ด ์์ ์ ์์ธ๋ฅผ ๋ฐ์์ํค๋ฏ๋ก handle ๋ฉ์๋์๋ ์์ธ ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋ฉ๋๋ค. handle ๋ฉ์๋๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ์์ธ๊ฐ ๋ฐ์ํ์ผ๋ฏ๋ก -1์ ๋ฐํํฉ๋๋ค.
2. whenComlete[Async]
whenComplete[Async] ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ ์์ธ๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํ๋, ์๋ก์ด ๊ฐ์ ๋ฐํํ์ง ์์ต๋๋ค. ์๋์ CompletableFuture์ ์ํฅ์ ๋ฏธ์น์ง ์๊ณ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ญํ ๋ง ํฉ๋๋ค.
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Exception!");
}
return 100;
}).whenComplete((res, ex) -> {
if (ex != null) {
System.out.println("์์ธ ๋ฐ์: " + ex);
}
});
์ด ์ฝ๋์์ CompletableFuture.supplyAsync() ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ์์ํ๋ฉฐ, ์ด ์์ ์ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค. whenComplete ๋ฉ์๋๋ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์ด๋ฅผ ์ฒ๋ฆฌํ์ง๋ง ์๋ก์ด ๊ฐ์ ๋ฐํํ์ง ์์ผ๋ฏ๋ก, ์๋์ CompletableFuture๋ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค.
๋ฐ๋ผ์ whenComplete[Async] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋๊ธฐ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋, ์์
์ค ๋ฐ์ํ ์์ธ๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ, ์ด๋ ์๋์ CompletableFuture์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
3. exceptionally[Async]
exceptionally[Async] ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ค ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋์ฒด ๊ฐ์ ๋ฐํํ๋ ์ญํ ์ ํฉ๋๋ค. ์์ธ๋ฅผ ์ธ์๋ก ๋ฐ์ ์ฒ๋ฆฌํ๋ฉฐ, ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋ฐํํ ๋์ฒด ๊ฐ์ ์ง์ ํฉ๋๋ค.
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("Exception!");
}
return 100;
}).exceptionally(ex -> {
System.out.println("์์ธ ๋ฐ์: " + ex);
return -1;
});
์ด ์ฝ๋์์ CompletableFuture.supplyAsync() ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ์์ํ๋ฉฐ, ์ด ์์ ์ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค. exceptionally() ๋ฉ์๋๋ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์ด๋ฅผ ์ฒ๋ฆฌํ๊ณ , ์์ธ๊ฐ ๋ฐ์ํ์ผ๋ฏ๋ก -1์ ๋ฐํํฉ๋๋ค.
๋ฐ๋ผ์ exceptionally[Async] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋๊ธฐ ์์
์ค ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์ ์ ํ ๋์ฒด ๊ฐ์ ๋ฐํํ ์ ์์ต๋๋ค.
์ ๋ฆฌ
๋น๋๊ธฐ ๋๊ธฐ / ์ทจ์ ์ฒ๋ฆฌ
1. get()
get() ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ฉฐ, ์์ ์ด ์๋ฃ๋ ๋๊น์ง ํธ์ถํ ์ค๋ ๋๋ฅผ ๋๊ธฐ ์ํ๋ก ๋ง๋ญ๋๋ค. ๋ธ๋กํน ๋ฐฉ์์ผ๋ก ๋์ํ๋ฏ๋ก get() ๋ฉ์๋๋ฅผ ํธ์ถํ ์ค๋ ๋๋ ์์ ์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ค๋ฅธ ์์ ์ ์งํํ์ง ์์ต๋๋ค.
๋ํ, get() ๋ฉ์๋๋ InterruptedException๊ณผ ExecutionException ๋ฑ์ ์ฒดํฌ๋ ์์ธ(Checked Exception)๋ฅผ ๋์ง๋๋ค. ๋ฐ๋ผ์ get() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ๋๋ try-catch ๋ธ๋ก์ ํตํด ์ด๋ฌํ ์์ธ๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
์๋๋ get() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์์ ์ฝ๋์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
try {
String result = future.get(); // ์์
์ด ์๋ฃ๋ ๋๊น์ง ๋๊ธฐ
System.out.println(result); // "Hello" ์ถ๋ ฅ
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
2. get(timeout, unit)
get(timeout, unit) ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ฉฐ, ์์ ์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์ ํํ ์ ์์ต๋๋ค. get() ๋ฉ์๋์ ์ ์ฌํ์ง๋ง, ์์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์ ํํ๋ ์ ์ด ๋ค๋ฆ ๋๋ค.
๋ง์ฝ ์ง์ ๋ ์๊ฐ ๋์ ์์ ์ด ์๋ฃ๋์ง ์์ผ๋ฉด TimeoutException์ด ๋ฐ์ํฉ๋๋ค. ์ฌ๊ธฐ์ ์๊ฐ ๋จ์๋ TimeUnit ์ด๊ฑฐํ์ ์ฌ์ฉํ์ฌ ์ง์ ํฉ๋๋ค. ๋ํ get(timeout, unit)์ ์์ ์ค ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ExecutionException์ ๋์ง๋ฏ๋ก, ์ด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด try-catch ๋ธ๋ก์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์๋๋ get(timeout, unit) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์์ ์ฝ๋์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000); // 2์ด ๋๊ธฐ
return "Hello";
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
try {
String result = future.get(1, TimeUnit.SECONDS); // 1์ด ๋์๋ง ๋๊ธฐ
System.out.println(result);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
3. join()
join() ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ฉฐ, ์์ ์ด ์๋ฃ๋ ๋๊น์ง ํ์ฌ ์ค๋ ๋๋ฅผ ๋๊ธฐ ์ํ๋ก ๋ง๋ญ๋๋ค. get() ๋ฉ์๋์ ์ ์ฌํ ์ญํ ์ ํ์ง๋ง join() ๋ฉ์๋๋ ์ฒดํฌ๋ ์์ธ๊ฐ ์๋ CompletionException์ด๋ผ๋ ์ธ์ฒดํฌ ๋ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค.
๋ํ, join() ๋ฉ์๋๋ ๋ธ๋กํน ๋ฉ์๋๋ก ์์ฉํ์ฌ, ํด๋น ๋ฉ์๋๊ฐ ํธ์ถ๋ ์ค๋ ๋๋ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๋ค๋ฅธ ์์ ์ ์ํํ์ง ์๊ณ ๋๊ธฐํฉ๋๋ค.
์๋๋ join() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์์ ์ฝ๋์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "Hello";
});
// join() ๋ฉ์๋๋ก ๋น๋๊ธฐ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
// ์ด ๋ฉ์๋๋ ์์
์ด ์๋ฃ๋ ๋๊น์ง ํ์ฌ ์ค๋ ๋๋ฅผ ๋ธ๋กํนํฉ๋๋ค.
String result = future.join();
System.out.println(result);
์ด ์ฝ๋์์ join() ๋ฉ์๋๋ฅผ ํตํด ๋น๋๊ธฐ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๋ํ ์์
์ด ์๋ฃ๋ ๋๊น์ง ์ค๋ ๋๋ฅผ ๋ธ๋กํนํ๊ธฐ ๋๋ฌธ์, ์์
์ด ์๋ฃ๋๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ ๋๋ฅผ ๊ณ์ ๋๊ธฐ ์ํ๋ก ์ ์งํฉ๋๋ค.
4. cancel(boolean mayInterruptIfrunning)
cancel(boolean mayInterruptIfRunning) ๋ฉ์๋๋ ๋น๋๊ธฐ ์์ ์ ์ทจ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ๋งค๊ฐ๋ณ์ mayInterruptIfRunning์ ์์ ์ด ์คํ ์ค์ผ ๋ ๊ทธ ์์ ์ ์ค๋จ์ํฌ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ๋ง์ฝ ์ด ๋งค๊ฐ๋ณ์๊ฐ true๋ก ์ค์ ๋๋ฉด, ์คํ ์ค์ธ ์์ ์ด ์๋ค๋ฉด ๊ทธ ์์ ์ ์ค๋จ์ํต๋๋ค.
์์ ์ด ์ฑ๊ณต์ ์ผ๋ก ์ทจ์๋๋ฉด true๋ฅผ ๋ฐํํ๋ฉฐ ์์ ์ด ์ด๋ฏธ ์๋ฃ๋์๊ฑฐ๋ ์ด๋ฏธ ์ทจ์๋์๊ฑฐ๋, ์ทจ์ํ ์ ์๋ ๊ฒฝ์ฐ์๋ false๋ฅผ ๋ฐํํฉ๋๋ค.
์๋๋ cancel(boolean mayInterruptIfRunning) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์์ ์ฝ๋์ ๋๋ค.
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000); // 2์ด ๋์ ๋๊ธฐ
return "Hello";
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
});
// cancel ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋น๋๊ธฐ ์์
์ ์ทจ์ํฉ๋๋ค.
// ์ด ๋ฉ์๋๋ ์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์ทจ์๋๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.
boolean isCancelled = future.cancel(true);
// ์์
์ทจ์ ์ฌ๋ถ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
// ์ด ์์ ์์๋ true๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
System.out.println(isCancelled);
์ด ์ฝ๋์์ cancel(true) ๋ถ๋ถ์ ๋น๋๊ธฐ ์์
์ ์ทจ์ํ๋ฉฐ, ์คํ ์ค์ธ ์์
์ด ์๋ค๋ฉด ๊ทธ ์์
์ ์ค๋จ์ํค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ด ์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์ทจ์๋๋ฉด true๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํฉ๋๋ค.
์ ๋ฆฌ