๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
BackEnd๐ŸŒฑ/Java

[Java] CompletableFuture๋กœ ๋น„๋™๊ธฐ ๋ฐ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ

by ์•ˆ์ฃผํ˜• 2023. 12. 12.

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์˜ ๊ณ„์ธต๊ตฌ์กฐ

์ฃผ์š” ํŠน์ง•

  1. ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ž‘์—… ๋™์‹œ์— ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ
    • CompletableFuture๋Š” ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ IO ์ž‘์—…์ด๋‚˜ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ๊ณผ ๊ฐ™์ด ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์—์„œ ๋งค์šฐ ํšจ์œจ์ ์ธ๋ฐ ๊ฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋Š” ์‹œ์ ์— ๋”ฐ๋ผ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ํ›„ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋“ฑ์˜ ๋ณต์žกํ•œ ํ๋ฆ„ ์ œ์–ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  2. ์ž‘์—…์˜ ๋ณ‘ํ•ฉ, ์ทจ์†Œ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋“ฑ์˜ ๊ธฐ๋Šฅ ์ œ๊ณต
    • CompletableFuture๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋“ฑ์˜ ๊ณ ๊ธ‰ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ทจ์†Œํ•˜๊ฑฐ๋‚˜, ์ž‘์—… ์ค‘ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  3. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์ง€์›์ด ํƒ์›”
    • 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๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
 

์ •๋ฆฌ

๋Œ“๊ธ€