[JAVA] ๋” ์ž๋ฐ”, Java 8 CompletableFuture

2022. 4. 11. 15:12ใ†JAVA/study

728x90

 

1๏ธโƒฃ Concurrent ์†Œํ”„ํŠธ์›จ์–ด ๋ž€?

๋™์‹œ์— ์—ฌ๋Ÿฌ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์†Œํ”„ํŠธ์›จ์–ด 

์˜ˆ) ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ ์œ ํŠœ๋ธŒ๋ฅผ ๋ณด๋ฉด์„œ ํ‚ค๋ณด๋“œ๋กœ ๋ฌธ์„œ์— ํƒ€์ดํ•‘์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. 

์˜ˆ) ๋…นํ™”๋ฅผ ํ•˜๋ฉด์„œ IntelliJ๋กœ ์ฝ”๋”ฉ์„ ํ•˜๊ณ  ์›Œ๋“œ์— ์ ์–ด๋‘” ๋ฌธ์„œ๋ฅผ ๋ณด๊ณ ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

2๏ธโƒฃ ์ž๋ฐ”์—์„œ ์ง€์›ํ•˜๋Š” Concurrent ํ”„๋กœ๊ทธ๋ž˜๋ฐ

: ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์‹ฑ(ProcessBuilder), ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ 

 

 

3๏ธโƒฃ ์ž๋ฐ” ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

Thread/ Runnable

 

- ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• 

Thread ์ƒ์†๋ฐ›์•„์„œ ๊ตฌํ˜„ 

Runnable ๊ตฌํ˜„ ๋˜๋Š” ๋žŒ๋‹ค

 

- ์“ฐ๋ ˆ๋“œ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ 

ํ˜„์žฌ ์“ฐ๋ ˆ๋“œ ๋ฉˆ์ถฐ๋‘๊ธฐ (sleep

๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ ๊นจ์šฐ๊ธฐ (interrupt)

๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ (join)

 

4๏ธโƒฃ Executors

: ๊ณ ์ˆ˜์ค€High-Level Concurrency ํ”„๋กœ๊ทธ๋ž˜๋ฐ 

์“ฐ๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์ž‘์—…์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ถ„๋ฆฌ 

๊ทธ๋Ÿฐ ๊ธฐ๋Šฅ์„ executors์—๊ฒŒ ์œ„์ž„ 

-> Runnable๊ฐ™์€๊ฑด low-level์ด๋ผ๊ณ ํ•จ.. 

 

Executor Service๋ž€ ๋ณ‘๋ ฌ ์ž‘์—… ์‹œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ œ๊ณต๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ 

Java์—์„œ ์“ฐ๋ ˆ๋“œํ’€์„ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ ์“ฐ๋Š” ์œ ํ‹ธ ํด๋ž˜์Šค 

ExecutorService์— Task๋งŒ ์ง€์ •ํ•ด์ฃผ๋ฉด ์นœ์ ˆํ•˜๊ฒŒ ์•Œ์•„์„œ ThreadPool์„ ์ด์šฉํ•ด์„œ Task๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์ค€๋‹ค. 

 

 

5๏ธโƒฃ Executors๊ฐ€ ํ•˜๋Š” ์ผ

์“ฐ๋ ˆ๋“œ ๋งŒ๋“ค๊ธฐ : ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉํ•  ์“ฐ๋ ˆ๋“œ ํ’€์„ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•œ๋‹ค. 

์“ฐ๋ ˆ๋“œ ๊ด€๋ฆฌ : ์“ฐ๋ ˆ๋“œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. 

์ž‘์—… ์ฒ˜๋ฆฌ ๋ฐ ์‹คํ–‰ : ์“ฐ๋ ˆ๋“œ๋กœ ์‹คํ–‰ํ•  ์ž‘์—…์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” API๋ฅผ ์ œ๊ณตํ•œ๋‹ค. 

 

6๏ธโƒฃ ์ฃผ์š” ์ธํ„ฐํŽ˜์ด์Šค 

Executors : execute(Runnable)

-> ExecutorService : Executor ์ƒ์†๋ฐ›์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ, Callable๋„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Executor๋ฅผ ์ข…๋ฃŒ ์‹œํ‚ค๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ Callable์„ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋Š” ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. 

 

-> ScheduledExecutorService : ExecutorService๋ฅผ ์ƒ์†๋ฐ›์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ํŠน์ • ์‹œ๊ฐ„ ์ดํ›„์— ๋˜๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ž‘์—…์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

์ข…๋ฅ˜

FixedThreadPool : ๊ณ ์ •๋œ ๊ฐฏ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์“ฐ๋ ˆ๋“œํ’€ -> ์ด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํ•ด๋‹น ๋จธ์‹ ์˜ cpu ์ฝ”์–ด์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ƒ์„ฑํ•˜๋ฉด ๋” ์ข‹์€ ํผํฌ๋จผ์Šค๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. 

CachedThreadPool : ์“ฐ๋ ˆ๋“œ๋ฅผ ์บ์‹ฑํ•˜๋Š” ์“ฐ๋ ˆ๋“œํ’€ -> ์ผ์ •์‹œ๊ฐ„ ๋™์•ˆ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ฒ€์‚ฌํ•˜์—ฌ 60์ดˆ ๋™์•ˆ ์ž‘์—…์ด ์—†์œผ๋ฉด pool ์—์„œ ์ œ๊ฑฐํ•œ๋‹ค. 

ScheduledThreadPool : 1๋ถ„์— ํ•œ๋ฒˆ์‹ ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ ์“ฐ๋ ˆ๋“œํ’€ 

SingleThreadExecutor : ํ•œ ๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์“ฐ๋ ˆ๋“œํ’€ 

ForkJoin Pool : ํฐ ์—…๋ฌด๋ฅผ ์ž‘์€ ์—…๋ฌด๋กœ ๋‚˜๋ˆ„์–ด ๋ฐฐ๋ถ„ํ•ด์„œ, ์ผ์„ ํ•œ ํ›„์— ์ผ์„ ์ทจํ•ฉํ•˜๋Š” ํ˜•ํƒœ 

-> Task์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋ถ„ํ• (fork) ํ•˜๊ณ  ๋ถ„ํ• ๋œ task๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋ฉด ๊ทธ๊ฒƒ์„ ํ•ฉ์ณ join ๋ฆฌํ„ดํ•ด์ค€๋‹ค. 

 

 

7๏ธโƒฃ Fork/Join ํ”„๋ ˆ์ž„์›Œํฌ 

ExecutorService์˜ ๊ตฌํ˜„์ฒด๋กœ ์†์‰ฝ๊ฒŒ ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์„œ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ๋„์™€์ค€๋‹ค. 

java์—์„œ ์“ฐ๋ ˆ๋“œํ’€์„ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ ์“ฐ๋Š” ์œ ํ‹ธ ํด๋ž˜์Šค 

-> ์œ ํ‹ธ ํด๋ž˜์Šค๋ž€ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์™€ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ์ผ์ ˆ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ , ์ •์  ๋ฉ”์„œ๋“œ์™€ ๋ณ€์ˆ˜๋งŒ์„ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งํ•œ๋‹ค. 

-> ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์˜ ๋ฉ”์„œ๋“œ์™€ ์ƒ์ˆ˜๋ฅผ ๋ชจ์•„์„œ ์บก์Šํ™”ํ•œ๊ฒƒ์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์ด๋‹ค. 

-> ๊ด€๋ จ๋œ ๋ฉ”์„œ๋“œ๋“ค๋ผ๋ฆฌ ๋ชจ์•„์„œ ํด๋ž˜์Šค๋กœ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ์— ์ค‘๋ณต๋œ ์ฝ”๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

8๏ธโƒฃ Callable๊ณผ Future

Callable : Runnable๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. 

Future : ๋น„๋™๊ธฐ์ ์ธ ์ž‘์—…์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. 

 

- ๊ฒฐ๊ณผ ๊ฐ€์ ธ์˜ค๊ธฐ get

-> submit() : ์ž‘์—… ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก Future๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. 

submit()๋Š” ์ž‘์—… ์ฒ˜๋ฆฌ ๋„์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ์Šค๋ ˆ๋“œ๋Š” ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ž‘์—…์„ ์œ„ํ•ด ์žฌ์‚ฌ์šฉ๋œ๋‹ค. 

-> ๋ธ”๋กํ‚น ์ฝœ 

-> ํƒ€์ž„ ์•„์›ƒ(์ตœ๋Œ€ํ•œ์œผ๋กœ ๊ธฐ๋‹ค๋ฆด ์‹œ๊ฐ„)์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

โ“ Blocking, Non-Blocking 

: Blocking๊ณผ Non-Blocking์€ ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ์— ์˜ํ•ด ๋ฐœ์ƒํ•œ๋‹ค. 

Blocking์€ ๋™๊ธฐ์  ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์—‡์„ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•œ๋‹ค. (๋™๊ธฐ์  ์ฒ˜๋ฆฌ๋ž€ ์ž‘์—…์„ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ˜„์žฌ ์ž‘์—…์ด ์ข…๋ฃŒ๋˜๋ฉด ๋‹ค์Œ ์ž‘์—…์ด ์ฒ˜๋ฆฌ๋œ๋‹ค.)

-> A ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง€๋ฉด ๋‹ค์Œ ์ž‘์—…์ธ B๊ฐ€ ๋Œ€๊ธฐํ•˜๋Š” ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง„๋‹ค. ์ด๋•Œ B๋Š” A ์‹คํ–‰์ด ์ข…๋ฃŒ๋œ ์ดํ›„ ํ˜ธ์ถœ๋˜๋Š”๋ฐ B๋Š” A์— ์˜ํ•ด Blocking ๋˜์—ˆ๋‹ค๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Non-Blocking ์€ ๋น„๋™๊ธฐ์  ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค. Blocking ๊ณผ๋Š” ๋ฐ˜๋Œ€๋กœ ํ•˜๋‚˜์˜ ์ž‘์—…์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋‹ค์Œ ์ž‘์—…์ด ๋Œ€๊ธฐํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , ํ•˜๋‚˜์˜ ์ž‘์—…์ด ์‹คํ–‰ํ•˜๋Š” ๋™์‹œ์— ๋‹ค์Œ ์ž‘์—…์ด ํ˜ธ์ถœ๋œ๋‹ค. 

 

- ์ž‘์—… ์ƒํƒœ ํ™•์ธํ•˜๊ธฐ isDone()  : ์ž‘์—…์„ ์™„๋ฃŒ ํ–ˆ์œผ๋ฉด true, ์•„๋‹ˆ๋ฉด false 

- ์ž‘์—… ์ทจ์†Œํ•˜๊ธฐ cancle() : ์ทจ์†Œ ํ–ˆ์œผ๋ฉด true, ๋ชปํ–ˆ์œผ๋ฉด false๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. 

-> ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ true๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ํ˜„์žฌ ์ง„ํ–‰์ค‘์ธ ์“ฐ๋ ˆ๋“œ๋ฅผ interrupt ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ ์ง„ํ–‰์ค‘์ธ ์ž‘์—…์ด ๋๋‚ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. 

 

- ์—ฌ๋Ÿฌ ์ž‘์—… ๋™์‹œ์— ์‹คํ–‰ํ•˜๊ธฐ invokeAll : ๋™์‹œ์— ์‹คํ–‰ํ•œ ์ž‘์—… ์ค‘์— ์ œ์ผ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—… ๋งŒํผ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค. 

 

- ์—ฌ๋Ÿฌ ์ž‘์—… ์ค‘์— ํ•˜๋‚˜๋ผ๋„ ๋จผ์ € ์‘๋‹ต์ด ์˜ค๋ฉด ๋๋‚ด๊ธฐ invokeAny() : ๋™์‹œ์— ์‹คํ–‰ํ•œ ์ž‘์—… ์ค‘์— ์ œ์ผ ์งง๊ฒŒ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—… ๋งŒํผ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค. -> ๋ธ”๋กํ‚น ์ฝœ 

 

 

9๏ธโƒฃ CompletableFuture

: ์ž๋ฐ”์—์„œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค 

๋ฌผ๋ก  Future์—์„œ ์–ด๋Š์ •๋„ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ–ˆ์ง€๋งŒ ์•ˆ๋˜๋Š” ๋ถ€๋ถ„๋“ค์ด ๊ฝค ์žˆ๋‹ค. 

  • Future๋ฅผ ์™ธ๋ถ€์—์„œ ์™„๋ฃŒ ์‹œํ‚ฌ ์ˆ˜ ์—†๋‹ค. ์ทจ์†Œํ•˜๊ฑฐ๋‚˜ get์— ํƒ€์ž„์•„์›ƒ์„ ์„ค์ •ํ•  ์ˆ˜๋Š” ์žˆ๋‹ค.
  • ๋ธ”๋กœํ‚น ์ฝ”๋“œ(get()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ์„œ๋Š” ์ž‘์—…์ด ๋๋‚ฌ์„ ๋•Œ ์ฝœ๋ฐฑ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.)
  • ์—ฌ๋Ÿฌ Future๋ฅผ ์กฐํ•ฉํ•  ์ˆ˜ ์—†๋‹ค. → Event ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ Event์— ์ฐธ์„ํ•˜๋Š” ํšŒ์› ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์šฉ api๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋น„๋™๊ธฐ๋กœ ์ž‘์—… ์‹คํ–‰ํ•˜๊ธฐ 

- ๋ฆฌํ„ด๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ runAsync() 

 

- ๋ฆฌํ„ด๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ supplyAsync() 

 

์ฝœ๋ฐฑ ์ œ๊ณตํ•˜๊ธฐ

- thenApply(Function) : ๋ฆฌํ„ด๊ฐ’์„ ๋ฐ›์•„์„œ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ฐ”๊พธ๋Š” ์ฝœ๋ฐฑ 

 

- thenAccept(Consumer<T>) : ๋ฆฌํ„ด๊ฐ’์„ ๋ฐ›์•„์„œ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝœ๋ฐฑ (๋ฆฌํ„ด ์—†์Œ) 

 

- thenRun(Runnable) : ๋ฆฌํ„ด๊ฐ’ ๋ฐ›์•„ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝœ๋ฐฑ 

-> thenRun ํ•จ์ˆ˜๋Š” ๊ฒฐ๊ณผ๊ฐ’, return ๊ฐ’ ๋ชจ๋‘ ํ•„์š” ์—†๋‹ค๋ฉด Runnable ์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. 

 

 

์กฐํ•ฉํ•˜๊ธฐ

thenCompose() : ๋‘ ์ž‘์—…์ด ์„œ๋กœ ์ด์–ด์„œ ์‹คํ–‰ํ•˜๋„๋ก ์กฐํ•ฉ 

 

thenCombine() : ๋‘ ์ž‘์—…์„ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๊ณ  ๋‘˜ ๋‹ค ์ข…๋ฃŒ ํ–ˆ์„ ๋•Œ ์ฝœ๋ฐฑ ์‹คํ–‰ 

 

allOf() : ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋ชจ๋‘ ์‹คํ–‰ํ•˜๊ณ  ๋ชจ๋“  ์ž‘์—… ๊ฒฐ๊ณผ์— ์ฝœ๋ฐฑ ์‹คํ–‰ 

anyOf() : ์—ฌ๋Ÿฌ ์ž‘์—… ์ค‘์— ๊ฐ€์žฅ ๋นจ๋ฆฌ ๋๋‚œ ํ•˜๋‚˜์˜ ๊ฒฐ๊ณผ์— ์ฝœ๋ฐฑ ์‹คํ–‰ 

 

์˜ˆ์™ธ ์ฒ˜๋ฆฌ

exceptionally(Function)

handle(BiFunction)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90