- ๋ชฉ์ฐจ
- ์๋ฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ Future
- 1 ๋๊ธฐ์ ๋น๋๊ธฐ ์ฝ๋
- 2 Future์ ์ญํ - ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ธฐ์ํ ์ธํฐํ์ด์ค
- 3 Future
- 4 Future์ ํ๊ณ - Callback ๋ถ์ฌ
- ์ ๋ฆฌ
- ์ฐธ๊ณ
- ๊ทธ์ธ - Runnable vs Callable
- ๊ทธ์ธ - execute()์ submit()
๋น๋๊ธฐ์ฒ๋ฆฌ์ ๋ํ ์ค์์ฑ์ ๋๋ ์ด ์ปค์ง๊ณ ์์ผ๋ฉฐ, ํ์ฌ๋ ์ปดํจํฐ ๋ฐ์ ์ ๋ฐ๋ผ ๋น๋๊ธฐ๋ ๊ฐ๋ ์ ๋ชจ๋ฅด๊ณ ์ ๋์ฉ๋ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์์ ๋๊ฐ ๋์๋ค.
์ด๋ฒ ๊ธ์ ์๋ฐ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ๋ฅผ ์ ๋ฆฌํ๋ ์๋ฆฌ์ฆ์ ์ฒซ๋ฒ์งธ ๊ธ์ด๋ค.
์๋ฐ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ์ญ์ฌ์๋ฐ๋ผ JDK 1.5์ ๋ฐํ๋ Future์ ๋ํด์ ๋จผ์ ์ด์ผ๊ธฐํด๋ณธ๋ค.
๊ธ ์์๋ถํฐ Future๋ ๋ฌด์์ด๋ฉฐ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ๋ํด์ ๋ค๋ฃจ๋ ๊ฒ์ ์ฌ์ค ๋ค๋ฅธ ๊ธ๋ ๋ง์ผ๋ฏ๋ก, ์ด๋ฒ ๊ธ์ Future๊ฐ ์ ํ์ํ์ง ๊ทธ๋ฆฌ๊ณ ๋ฌด์์ด ์ข์์ง ์์๋ณธ๋ค.
๊ทธ๋ฆฌ๊ณ Future์ ํ๊ณ์ ์ ๋๋ก๋ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ํ๋ ์ด์ ๋ฅผ ์ดํด๋ณด๋ฉฐ, ๋ค์์ผ๋ก ๋์จ ๋น๋๊ธฐ ํ๋ ์์ํฌ์ธ CompletableFuture ๋ด์ฉ์ ๋ฐ๋ฐฅ์ ๊น์๋ณด๋ ค๊ณ ํ๋ค.
์ด๋ฒ ๊ธ์ ๋ด์ฉ์ ํ์๊ฐ ์ง์ ํ ์คํธํ๋ฉฐ ์ดํดํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ฒ์ด๋ค. ํ๋ฆฐ ๋ด์ฉ์ด ์์ ์ ์๋ค.
์ฐ์ ๋ณธ๊ฒฉ์ ์ผ๋ก Future์ ์์๋ณด๊ธฐ์ ์์ ์๋ฐ๋ฅผ ์ด์ฉํ์ฌ ๋๊ธฐ๋ก ๋์ํ๋ ์ฝ๋๋ฅผ ์ดํด๋ณด์.
๋๊ธฐ (Synchronous)๋ก ๋์ํ๋ ๊ฐ๋จํ ์์๋ฅผ ์ดํด๋ณธ๋ค.
public class FutureEx_1_synchronism {
public static void main(String[] args) throws InterruptedException {
printAfterSeconds("Start", 3000);
printAfterSeconds("In Progress", 2000);
printAfterSeconds("End", 1000);
}
private static void printAfterSeconds(String text, long millis) throws InterruptedException {
Thread.sleep(millis);
System.out.println(text);
}
}์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
[main] Start
[main] In Progress
[main] End
์คํ ์์๋ ์๋์ ๊ฐ๋ค.
- 3์ด sleep์ดํ Start ์ถ๋ ฅ
- Start๊ฐ ์ถ๋ ฅ๋๊ณ ๋์ 2์ด sleep์ดํ In Progress ์ถ๋ ฅ
- In Progress๊ฐ ์ถ๋ ฅ๋๊ณ ๋์ 1์ด sleep์ดํ End ์ถ๋ ฅ
์คํ๊ฒฐ๊ณผ์ ์์๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, ํ๋์ ์ค๋ ๋์์ ๋ ๊ฐ์ Print๊ฐ ๋๊ธฐ/๋ธ๋กํน ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
์ด๋ค๊ฐ? ๊ต์ฅํ ๊ฐ๋จํ๋ฉฐ, ์ง๊ด์ ์ด๊ณ ์ดํดํ๊ธฐ๋ ์ฝ๋ค.
โ๏ธ ํ์ง๋ง ๋๊ธฐ๋ฐฉ์์ ์๋์ ๊ฐ์ด ๊ฐ๊ฐ์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ์ฃผ์ด์ง ๋๊น์ง ์๋ฌด๊ฒ๋ ๋ชปํ๊ณ ๋๊ธฐํด์ผํ๋ ๋จ์ ์ด ์๋ค.

์ด 6์ด์ ์๊ฐ์ด ์์๋๋ค.
์ง๊ธ์ ๊ฐ๋จํ ์์๋ฅผ ์ํด ํน์ ํ ์คํธ๋ฅผ ๋ช์ดํ์ ์ถ๋ ฅํ๋ ์์์ด์ง๋ง,
๋ง์ฝ ํ๋์ ์ค๋ ๋์์์ ๋๊ธฐ์ ์ผ๋ก ์ค๋๊ฑธ๋ฆฌ๋ ์ฌ๋ฌ๊ฐ์ง์ผ์ ์คํํ๋ฉด ์ฒ๋ฆฌ์๊ฐ์ด ์ ํ์ ์ผ๋ก ๋์ด๋ ์ ๋ฐ์์๋ค. - ์ค์
์ด๊ฒ ๋ฐ๋ก ๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์์ ๋ฌธ์ ์ด๋ฉฐ, ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์์ด ํ์ํ ์ด์ ์ด๊ธฐ๋ํ๋ค.
์ ํํํ์๋ฉด ์ ๋ฐฉ์์
๋๊ธฐ/๋ธ๋กํน์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ ์์๋ฅผ ๋น๋๊ธฐ๋ก ์คํํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๋น๋๊ธฐ๋ก ๋์ผํ ์์ ์ ์ํํ๋ฉด ์๋์ ๊ฐ๋ค.
public class FutureEx_2_execute {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
es.execute(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
System.out.println("Start");
});
es.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println("Process");
});
es.execute(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("End");
});
es.shutdown();
}
}์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค. (์ฐ์ execute()์ด ๋ฌด์์ธ์ง๋ ์์ง์์๋๋๋ค.)
[pool-1-thread-3] End
[pool-1-thread-2] Process
[pool-1-thread-1] Start
์คํ ์์๋ ์๋์ ๊ฐ๋ค.
- Start, Process, End ์์ผ๋ก 3์ด, 2์ด, 1์ด๋ฅผ sleepํ๊ณ ํ ์คํธ๋ฅผ ์ถ๋ ฅํ๋๋ก ๋น๋๊ธฐ๋ก ์์ฒญํ๋ค.
- ๊ฐ ์์ ์ ์ฃผ์ด์ง ์๊ฐ๋งํผ sleepํ๊ณ ํ ์คํธ๋ฅผ ์ถ๋ ฅํ๋ค.
์ฌ๊ธฐ์ ๋์ฌ๊ฒจ๋ด์ผํ ๋ถ๋ถ์ ์คํ ๊ฒฐ๊ณผ๊ฐ End์ด ๋จผ์ ์ถ๋ ฅ๋๊ณ , ๊ทธ ๋ค์ Process, ๋ง์ง๋ง์ผ๋ก Start๊ฐ ์ถ๋ ฅ๋์๋ค๋ ๊ฒ์ด๋ค.
๋ํ, 6์ด ๊ฑธ๋ฆฌ๋ ๋ชจ๋ ์์ ์ด 3์ด๋ง์ ๋๋ฌ๋ค.
์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ ค๋ณด๋ฉด ์๋์๊ฐ๋ค.

์ด 3์ด์ ์๊ฐ์ด ์์๋๋ค.
๊ทธ๋ฆผ์์๋ ์ฝ๊ฒ ์ ์ ์๋ฏ์ด, ๋น๋๊ธฐ๋ ๋๊ธฐ์๋ ๋ค๋ฅด๊ฒ CPU ์์๋ค์ ์ต๋ํ ์ฌ์ฉํด์ idle(๋๊ณ ์๋)ํ ์์ ์ด ์๋๋กํจ์ผ๋ก์จ ๊ฐ์ ์์ ์ด๋ผ๋ ๋ ๋น ๋ฅด๊ฒ ์์ ์ ์๋ฃํ ์ ์๋ค.
์ด๊ฒ ๋ฐ๋ก ๋น๋๊ธฐ๊ฐ ์ข์ ๊ฐ์ฅ ํฐ ์ด์ ์ด๊ธฐ๋ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ ํํํ์๋ฉด ์ ๋ฐฉ์์ ๋น๋๊ธฐ/๋
ผ๋ธ๋กํน์ด๋ค.
์ฌ๊ธฐ์
์ํ! ํธ์ถ๋๋ ํจ์์ ์์ ์๋ฃ๋ฅผ ํธ์ถํ ํจ์๊ฐ ์ ๊ฒฝ์ฐ์ง ์์ผ๋ฏ๋ก ๋น๋๊ธฐ๊ตฌ๋! ๊ทธ๋ฆฌ๊ณ ํธ์ถํ๊ณ ๋ฐ๋ก ๋ฆฌํด๋ฐ์ผ๋ ๋ ผ๋ธ๋กํน์ด๊ตฌ๋!๋ฅผ ์ดํดํด์ผํ๋ค.๋ง์ฝ ์ดํด๊ฐ ์๋๋ค๋ฉด 4๊ฐ์ง์ I/O ๋ฐฉ์์ ์ฐจ์ด์ ์ ์ ๋๋ก ์ดํดํ๊ณ ์ค๋๊ฒ ์ข๋ค.
๊ทธ๋ ๋ค๊ณ ๋ฌด์กฐ๊ฑด ๋น๋๊ธฐ ๋ฐฉ์์ด ์ข์ ๊ฒ๋ง์ ์๋๋ค. ์ ๋๋ก ์๊ณ ์ฌ์ฉํด์ผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. ์ ๋๋ก ๋ชจ๋ฅด๋ฉด ์คํ๋ ค ์ญํจ๊ณผ๊ฐ ๋ ์ ์๋ค.
์์ ๊ฐ๋จํ ๋๊ธฐ์ ๋น๋๊ธฐ์ฝ๋๋ก ๋น๋๊ธฐ๊ฐ ์ด๋ค ์ ์์ ์ข์์ง ์์๋ณด์๋ค.
๊ฐ๋จํ ์ ๋ฆฌํ์๋ฉด, ๋น๋๊ธฐ ๋ฐฉ์์ ๋์์ฑ์ ํ์ฉํ์ฌ CPU ์์์ ์ต๋ํ์ผ๋ก ํ์ฉํ์ฌ ๋ ๋น ๋ฅด๊ฒ ํน์ ์์ ์ ์ํํ ์ ์๋ค.
ํ์ง๋ง ๋น๋๊ธฐ๋ ๋ฌผ๋ก ๋จ์ ์ด ์ฌ๋ฌ๊ฐ์ง ์กด์ฌํ๋ค. ์๋ฅผ ๋ค์ด, ์คํ ๊ฒฐ๊ณผ๋ฅผ ์์ธกํ๊ธฐํ๋ค๊ณ , ์๋ชป์ฌ์ฉํ๋ฉด CPU ์ฌ์ฉ๋์ด ๊ต์ฅํ ์ฆ๊ฐํ ์๋ ์๋ค.
๊ทธ๋ฌ๊ธฐ์ ๋น๋๊ธฐ ๋ก์ง์ ๊ตฌ์ฑํ ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์๊ณผ Flow๋ฅผ ์ ๋๋ก ์ดํดํ๊ณ ์ฌ์ฉํ๋ ๊ฒ์ด์ข๋ค.
์ด๋ฒ ์ฅ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์์ ์ ๋๋ก ์ดํดํ๊ธฐ์ํด ๊ผญ ์์์ผํ๋ ๋น๋๊ธฐ Task ์ฒ๋ฆฌํ๋ ๋ฐฉ์์๋ํด์ ์์๋ณธ๋ค.
์ด๋ฅผ ํตํด Future๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์์๋ณธ๋ค.
๐โโ๏ธ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ์์๋ ํฌ๊ฒ ๋๊ฐ์ง๊ฐ ์๋ค.
- ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์์๋ ๊ฒฝ์ฐ
- ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ
์์์ ์ดํด๋ณธ ๊ฐ๋จํ ๋น๋๊ธฐ ์์๋ ์ฌ์ค ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์์๋ ๊ฒฝ์ฐ์ด๋ค.
๋ค์๋งํด, Start, Process, End๋ฅผ ์ถ๋ ฅํ๋ ์ฒ๋ฆฌ์ ์๋ก ์ฐ๊ด๊ด๊ณ๊ฐ ์ ํ์์ผ๋ฉฐ, ๋์๊ฐ์ ์๋ก์ ์์
์๋ฃ ์ฌ๋ถ๊ฐ ์ฐ๊ด์์ผ๋ฏ๋ก ์๋ก์ ์ผ์ ์ง์คํ ์ ์์๋ค.
์ด๋ ๊ฒ ํ ์คํธ๋ก๋ง ๋งํ๋ฉด ์ดํดํ๊ธฐ๊ฐ ํ๋๋, ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์์๋ ๊ฒฝ์ฐ์ ํ์ํ ๊ฒฝ์ฐ๋ฅผ ์์๋ฅผํตํด ์ดํด๋ณด์.
๐โโ๏ธ ๋จผ์ ์์์ ์ดํด๋ณธ ๋์ผํ ์์ ๋ง์ง๋ง์ Exit๋ฅผ ํ๋ฒ ๋ ์ถ๋ ฅํ๋ ์์๋ฅผ ์ดํด๋ณด์.
public class FutureEx_2_execute {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
es.execute(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
System.out.println("Start");
});
es.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println("Process");
});
es.execute(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println("End");
});
// ์๋ก ์์ฑ๋ ์ฝ๋
System.out.println("Exit")
es.shutdown();
}
}์คํ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
[main] Exit
[pool-1-thread-3] End
[pool-1-thread-2] Process
[pool-1-thread-1] Start
๊ฒฐ๊ณผ์์ ์ ์ ์๋ฏ์ด, 4๊ฐ์ ์ค๋ ๋๊ฐ ๊ฐ๊ฐ ๋น๋๊ธฐ๋ก ๋์ํ๋ค.
์ฌ๊ธฐ์ ๋์ฌ๊ฒจ๋ด์ผํ ๋ถ๋ถ์ ํธ์ถํ๋ ์ชฝ์ธ main ์ค๋ ๋์์์ Exit์ด ๊ฐ์ฅ ๋จผ์ ์ถ๋ ฅ๋์์ผ๋ฉฐ, Sleep์ ๋ฐ๋ผ ์ค๋ฆ์ฐจ์์ผ๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ main์์ ๋ค๋ฅธ ๋น๋๊ธฐ๋ก ์์ฒญํ ๊ฐ๊ฐ์ ์ค๋ ๋๊ฐ ์๋ก์ ์์ ์๋ฃ ์ฌ๋ถ๋ฅผ ์ ํ ์ ๊ฒฝ์ฐ์ง ์๋๋ค.
์ด๋ ๊ฒ ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํด ๋ฐ์ ํ์๊ฐ ์์ ๊ฒฝ์ฐ ์๋ฐ์ Executor.execute(Runnable runnable)์ ์ฌ์ฉํ๋ฉด ์ค๋ ๋ ํ์ ํ์ฉํ์ฌ ํจ๊ณผ์ ์ผ๋ก ์ค๋ ๋๋ฅผ ์ ์ดํ ์ ์๋ค.
์ด์ ๊ฐ์ ๋ํ์ ์ธ ์์๋ก ๋ก๊ทธ ๊ธฐ๋ก์ด ์๋ค.
์ด๋ฒ ๊ธ์์ ๋ค๋ฃจ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์์ ๋ชจ๋
Concurrency(๋ณํ) ์ฒ๋ฆฌ ๋ฐฉ์์ด๋ค.
์์ ๊ฐ์ด ๋น๋๊ธฐ/๋ ผ๋ธ๋กํน ๋ฐฉ์์ผ๋ก๋ง ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ผ๋ฉด ๋ชจ๋ ๊ฐ๋ฐ์๋ค์ ํ๋ณตํ๊ฒ ๊ฐ๋ฐํ ์ ์์ ๊ฒ์ด๋ค.
ํ์ง๋ง ํ์ค์์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋ฅผ ์์ฒญํ๋ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ๊ฐ ํจ์ฌ ๋ง๋ค.
์๊ตฌ์ฌํญ์ ์กฐ๊ธ ๋ ์ถ๊ฐํ์ฌ ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณด์.
๐ค ๋ง์ฝ 4๊ฐ์ ์ค๋ ๋์ ๋น๋๊ธฐ๋ก ์์ฒญํ์ฌ ๊ฐ๊ฐ Start, Process, End, Exit๋ฅผ ์์๋๋ก ๋ฆฌํด๋ฐ์, ์ด๋ฅผ ํ๋์ ๋ฌธ์์ด๋ก ํฉ์ณ ์ฒ๋ฆฌํด์ผํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น??
์๋ก์ด ์๊ตฌ์ฌํญ์ ๋ณด๋ฉด ๊ฐ๊ฐ์ ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ ์ฐ๊ด ๊ด๊ณ๊ฐ ์๊ธด ๊ฒ์ ์ ์ ์๋ค.
์ด๋ ์๋ง ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ ์ฒ์์ ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด๋ค.
ํ์ง๋ง ์ด๋ ๋ค์ CPU ์์์ ์ญ๋ถ ํ์ฉํ์ง๋ชปํด ๋นํจ์จ์ ์ผ๋ก ์ฐ์ฐ์ ์ฒ๋ฆฌํ๊ธฐ๋๋ฌธ์ ์ข์ ๋ฐฉ๋ฒ์ด ์๋๋ค.
์ด๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ๋น๋๊ธฐ/๋ ผ๋ธ๋กํน์ผ๋ก ์ฐ์ฐ์ ์ฒ๋ฆฌํ๊ณ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ๋ฐ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ฒ ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ๋ฐ์ ์ ์๋๋ก ์๋ฐ์์ ์ถ์ํํ ์ธํฐํ์ด์ค๊ฐ ๋ฐ๋ก Future์ธํฐํ์ด์ค๋ค.
๐โโ๏ธ Future - ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ธฐ์ํ ์ธํฐํ์ด์ค
Javadoc - Future์ ๊ฐ์ฅ ์ฒซ๋ฌธ์ฅ์ ์๋์ ๊ฐ์ด ์ ํ์๋ค.
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation
Future์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ธ๋ค. ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋์๋์ง ํ์ธํ๊ณ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์ ์ ์๋ค (๋ฐํ ๋ฐ์ ์ ์๋ค.).
ํ๋ง๋๋ก Future์ ๋น๋๊ธฐ์ ์ฐ์ฐ์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ธฐ ์ํ ์ธํฐํ์ด์ค์ด๋ค.
์์๋ฅผ ํตํด Future์ ์ฌ์ฉ ์์๋ฅผ ์ดํด๋ณด์.
public class FutureEx_3_submit_and_future {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
// ๋น๋๊ธฐ ์์ฒญ
Future<String> startFuture = es.submit(() -> {
Thread.sleep(3000);
return "Start";
});
// ๋น๋๊ธฐ ์์ฒญ
Future<String> processFuture = es.submit(() -> {
Thread.sleep(2000);
return "Process";
});
// ๋น๋๊ธฐ ์์ฒญ
Future<String> endFuture = es.submit(() -> {
Thread.sleep(1000);
return "End";
});
// ... main์์์ ์์
์คํ ...
// ๋น๋๊ธฐ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ์ถ๋ ฅ.
String start = startFuture.get();
System.out.println(start);
String process = processFuture.get();
System.out.println(process);
String end = endFuture.get();
System.out.println(end);
// ๋น๋๊ธฐ๋ก ์์ฒญํ ์์
์ ๊ฒฐ๊ณผ๋ฅผ ํฉ์ณ์ ์ถ๋ ฅ.
System.out.println(start + " " + process + " " + end);
System.out.println("Exit");
es.shutdown();
}
}์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
[main]Start
[main]Process
[main]End
[main]Start Process End
[main]Exit
์คํ ์์๋ ์๋์ ๊ฐ๋ค.
- main ์ค๋ ๋๊ฐ ๊ฐ๊ฐ ์ฃผ์ด์ง ์๊ฐ๋งํผ sleepํ๊ณ
Start,Process,End๋ฅผ ๋ฐํํ๋ Task (์ฒ๋ฆฌ)์ ์ค๋ ๋ ํ์ ์์ฒญํ๋ค.- ์ด๋, main์ ๋ ผ๋ธ๋กํน์ผ๋ก ์์ฒญํ๋ค. ์ฆ, ์ ์ด๊ถ์ main์๊ฒ ๋ฐ๋ก ๋ฐํํ๋ค.
- main์ ์์ ์ ์์
์ ์คํํ๋ค, ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ๊ฒฐ๊ณผ๋ค์ ์ป๊ธฐ์ํด
Future.get()์ ์์ฒญํ๋ค.- ์ดํ์ ์๊ธฐํ๊ฒ ์ง๋ง, ์ด๋ main์ ๋น๋๊ธฐ๋ก ์์ฒญํ Task๊ฐ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํ๊ธฐ์ ๊น์ง ๋ธ๋กํน๋๋ค.
- main์ ๊ฐ๊ฐ์
Future๋ก๋ถํฐ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ๋ฌธ์์ด์ ํฉ์ณ ์ถ๋ ฅํ๋ค.
๐โโ๏ธ Future์ ๋น๋๊ธฐ์ ์ฐ์ฐ์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ธฐ ์ํ ์ธํฐํ์ด์ค์ด๋ค.
์์ ๊ฐ์ด Future์ ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํด ์ฌ์ฉ๋๋ ์ธํฐํ์ด์ค์ด๋ค.
๊ทธ๋ฆฌ๊ณ Java์ ์ค๋ ๋ ํ์ ์ถ์ํํ ExecutorService์ธํฐํ์ด์ค๋ submit() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด Future๋ฅผ ๋ฐํํ๋ค.
๊ฐ๋ฐ์๋ submit()์ผ๋ก ์์ฒญํ ๋น๋๊ธฐ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ Future๋ก ์ ๊ทผํ ์ ์๋ค.
๋ฌผ๋ก
Future์์ด ์ง์ ์ค๋ ๋๋ฅผ ๊ตฌํํด์, ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ ๊ฐ์ฒด๋ฅผ ์ง์ ๊ตฌํํด๋๋๋ค.๋ค๋ง ์ง์ ๊ตฌํ์ ๊ต์ฅํ ๋ฒ๊ฑฐ๋ก์ฐ๋ฉฐ, ์ค๋ ๋ ์์ ๋ ์ ๊ฒฝ์จ์ผํ๋ค.
Java๋ ์ด๋ฌํ ์์ ์
Future๋ก ์ถ์ํ์ํจ ๊ฒ์ด๋ค.
๐ค ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ง๋ณด๋ฉด ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ๊ณผ ์ฐจ์ด๊ฐ ์์ด๋ณด์ด๋๋ฐ, ์ด๋ค ์ฐจ์ด๊ฐ์๋๊ฐ? - Future๋ฅผ ํตํ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฐฉ์์ ์ฅ์
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ง๋ณด๋ฉด ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ๊ณผ ์ฐจ์ด๊ฐ ์์ด๋ณด์ธ๋ค.
๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ์ฝ๋๋ ๊ต์ฅํ ๊ฐ๋จํ๋ฏ๋ก ์๋ตํ๋ค.
ํ์ง๋ง ์๋์ ๊ฐ์ด ์คํ๊ฒฐ๊ณผ๋ฅผ๋ณด๋ฉด ํฐ ์ฐจ์ด๊ฐ์๋ค.
๊ฒฐ๊ณผ์์๋ ์ ์ ์๋ฏ์ด, Future๋ฅผ ํตํ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ ์ฝ 3์ด, ๋๊ธฐ๋ฅผ ์ฝ 6์ด์ด๋ค.
์ง๊ธ์ ๋ ๋ฐฐ์ง๋ง, ๋ง์ฝ Task๊ฐ ๋ง๋ค๋ฉด ๋ช ๋ฐฐ์ด์ ์ฐจ์ด๊ฐ๋๋ค.
์ด๋ ๊ฒ ์ฐจ์ด๋๋ ์ด์ ๋ ์์ ์ดํด๋ณธ ๋๊ธฐ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ์คํ ๊ฒฐ๊ณผ๊ฐ ์ฐจ์ด๊ฐ๋๋ ๊ฒ๊ณผ ๋์ผํ๋ค.
- ๋๊ธฐ - 3์ด sleep ํ
Start๋ฐํ -> 2์ด sleep ํProcess๋ฐํ -> 1์ด ํ sleep ํEnd๋ฐํ - ๋น๋๊ธฐ - ๋์ผํ ์๊ฐ์ ๊ฐ๊ฐ 3์ด, 2์ด, 1์ด sleep ์ดํ ๊ฐ๊ฐ์ ํ ์คํธ๋ฅผ ๋ฐํ.
์ฆ, Future.get()์ ํธ์ถํ๋ฉด ํด๋น ์ค๋ ๋๋ ๋ธ๋กํน๋์ง๋ง, ์ฌ์ ํ ์ด์ ์ ๋น๋๊ธฐ๋ก ์์ฒญํ ์์
๋ค์ ๋น๋๊ธฐ๋ก ๋์ํ๋ค.
๊ทธ๋ฆผ์ ํตํด ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.

์ถ์ฒ: https://sites.google.com/site/robhamk/java/completablefuture
์ ํํ ๋งํ๋ฉด ๋น๋๊ธฐ ์์์ ๊ฒฝ์ฐ
Future.get()์ ํธ์ถํ๊ธฐ์ ๊น์ง๋น๋๊ธฐ/๋ ผ๋ธ๋กํน์ผ๋ก ๋์ํ์ง๋ง,
get()์ ํธ์ถํ๋์๊ฐ๋ถํฐ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๊ธฐ์ ๊น์ง๋ธ๋กํน๊ฐ ๋๋ค.์ ๋ง ๋น๋๊ธฐ๋ก ๋์์ํค๋ ค๋ฉด Callback์ ๊ฐ์ด ๋๊ฒจ์ผํ๋ค. ์ด์ ๊ด๋ จํด์๋ ์๋์์ ๋ ์์ธํ ๋ค๋ฃฐ ์์ ์ด๋ค.
๐โโ๏ธ Future.get๋ ๋, submit์ผ๋ก ๋๊ธด Callable ์์
์ ๊ทธ์ ์์ผ ์คํํ๋ ๊ฒ์ด ์๋, ThreadPool์ submitํ์๋ง๋ค ์คํ๋๋ค. - ์ค์
ํํ ์ฐฉ๊ฐํ๋ ๊ฒ์ค ํ๋๋ก, Future.get()์ ํธ์ถํด์ผ ๋น๋๊ธฐ๋ก ์์ฒญํ Task๊ฐ ์คํ๋๋ค๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง ์ค์ ๋ก ThreadPool์ Task๋ฅผ submitํ์๋ง์ ๋น๋๊ธฐ๋ก Task๊ฐ ์คํ๋๋ค.
public class FutureEx_4_submit_and_future_2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
// 3๊ฐ์ง์ ์์
์ ๋ณ๋ ฌ์ ์ผ๋ก ์คํ์ํค๊ธฐ์ํด ThreadPool์ ์์
๋ค์ submitํ๋ค.
Future<String> result1 = es.submit(() -> {
System.out.println("Async Hello Task Started!");
Thread.sleep(1_000);
return ThreadPrintUtils.getCurrentThreadName() + "Async Hello ";
});
Future<String> result2 = es.submit(() -> {
System.out.println("Async World Task Started!");
Thread.sleep(2_000);
return ThreadPrintUtils.getCurrentThreadName() + "Async World ";
});
Future<String> result3 = es.submit(() -> {
System.out.println("Async Test Task Started!");
Thread.sleep(3_000);
return ThreadPrintUtils.getCurrentThreadName() + "Async Test ";
});
System.out.println("Exit");
// Future.get๋ ๋, submit์ผ๋ก ๋๊ธด Callable ์์
์ ๊ทธ์ ์์ผ ์คํํ๋ ๊ฒ์ด ์๋, ThreadPool์ submitํ์๋ง๋ค ์คํ๋๋ค.
// ์ฌ๋ฌ ์์
๋ค์ด ๋น๋๊ธฐ์ ์ผ๋ก ๊ณ์ ๋์ํ๋ค๊ฐ, get ๋ฉ์๋๊ฐ ํธ์ถ๋์์๋ blocking ๋๋ฉด์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ. (Thread.join๊ณผ ์ ์ฌํ๋ค)
System.out.println(result1.get());
System.out.println(result2.get());
System.out.println(result3.get());
es.shutdown();
}
}
// ๊ฒฐ๊ณผ
Async Hello Task Started!
Async Test Task Started!
Exit
Async World Task Started!
[pool-1-thread-1]Async Hello
[pool-1-thread-2]Async World
[pool-1-thread-3]Async Test์ ๊ฒฐ๊ณผ์์๋ ์ ์ ์๋ฏ์ด, ThreadPool์ ๋๊ธด Task๋ค์ ๋ฐ๋ก ๋น๋๊ธฐ๋ก ์คํ๋๊ฒ๋๋ค.
๊ทธ๋ฆฌ๊ณ Future.get()๋ฅผ ํตํด ํด๋น ๋น๋๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ ๋ฟ์ด๋ค.
๋ง์ฝ ๊ฒฐ๊ณผ๊ฐ ์ด๋ฏธ ๋์๋ค๋ฉด Blocking์ด ๋์ง ์์ง๋ง, ์์ง ์คํ์ค์ด๋ผ๋ฉด Blocking๋๋ค.
์์ ๋๊ธฐ์ ๋น๋๊ธฐ์ ์ฐจ์ด์ ์ ๋ฌด์์ด๋ฉฐ, Future๊ฐ ์ด๋ค ์ญํ ์ํ๋์ง ์ดํด๋ณด์๋ค.
์ด๋ฒ ์ฅ์์ Future์ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ์ ๋ฆฌํ ์์ ์ด๋ค.
์ด๋ฒ ์ฅ์ ๋ด์ฉ์ ์ฌ์ค ๋ค๋ฅธ ๋ธ๋ก๊ทธ์๋ ๋ง์ผ๋ฏ๋ก ์คํตํด๋ ๋ฌด๋ฐฉํ๋ค.
๐โโ๏ธ Future๋ - pending completion
- Java 1.5๋ถํฐ ๋์จ ์ธํฐํ์ด์ค๋ก ๋น๋๊ธฐ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ธฐ์ํด ์ฌ์ฉ๋๋ค.
- ๋น๋๊ธฐ ์ฒ๋ฆฌ์ด ์๋ฃ๋์๋์ง ํ์ธํ ์ ์์ผ๋ฉฐ, ์ฒ๋ฆฌ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ ค์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
Future๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฅธ ์ค๋ ๋์ ์ ๋ฌํ ์ ์์ผ๋ฉฐ,Future์ ๋ด๋ถ์ ์ผ๋ก ์ค๋ ๋ ์์ ํ๋ค.- ๊ตณ์ด
synchronizedํค์๋๋ฅผ ์ฌ์ฉํ์ง์์๋๋๋ค.
- ๊ตณ์ด
Future์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ป๋ ๋ฐฉ์์ผ๋ก ๋์ํ๊ธฐ๋๋ฌธ์, ์ง์ฐ ์๋ฃ (pending completion)์ด๋ผ๊ณ ๋ ๋ถ๋ฆฐ๋ค.
๐โโ๏ธ Future๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋
public interface Future<V> {
boolean cancel(boolean var1);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}get()- ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋.
- ๋ง์ฝ ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ๋ฆฌํด(์๋ฃ)๋์ง ์์๋ค๋ฉด, ๊ฒฐ๊ณผ๊ฐ ๋์ฌ๋๊น์ง Blocking๋์ด ๊ธฐ๋ค๋ฆฐ๋ค.
get(Long time, TimeUnit unit)get()๋ฉ์๋๋ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ๋๊น์ง Blocking๋์ด ๊ธฐ๋ค๋ฆฌ๊ธฐ๋๋ฌธ์, ์๋ชปํ๋ฉด Thread๊ฐ ๋ฌดํํ๊ฒ ๋๊ธฐํ์ฌ ํ๋ก๊ทธ๋จ์ด ์๋ต์๋ ์ํ๋ก ๋ง๋ค ์ ์๋ค.- ์ด๋ก์ธํด
Future์ Timeout์ ์ค์ ํ ์ ์๋ค. ํด๋น ๋ฉ์๋๋ฅผ ํตํด ์ผ์ ์๊ฐ๋ด์ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ์ง์์ผ๋ฉดTimeoutException`์ ๋์ง๋ค.
isDone()- ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ์๋ฃ์ฌ๋ถ๋ฅผ boolean์ผ๋ก ๋ฐํํ๋ค.
isCancelled()- ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ์ทจ์ ์ฌ๋ถ๋ฅผ boolean์ผ๋ก ๋ฐํํ๋ค.
cancel(boolean var1)- ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ์ ์ค๋จ์ ์๋ํ๋ ๋ฉ์๋์ด๋ค. ์ด๋ ๋ง์ฝ ์ฐ์ฐ์ด ์ด๋ฏธ ์๋ฃ๋์๋ค๋ฉด
cancel()๋ฉ์๋๋ ๋์ํ์ง์๋๋ค. - ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ์ ์ค๋จ ์ฑ๊ณต์ฌ๋ถ๋ฅผ boolean์ผ๋ก ๋ฐํํ๋ค.
- ๋งค๊ฐ๋ณ์๋ก true๋ฅผ ์ ๋ฌํ๋ฉด ๋น๋๊ธฐ๋ก ์์ฒญํ ์ค๋ ๋์
interrupt()๋ฅผ ๋ฐ์์ํจ๋ค.
- ๋น๋๊ธฐ๋ก ์์ฒญํ ์ฒ๋ฆฌ์ ์ค๋จ์ ์๋ํ๋ ๋ฉ์๋์ด๋ค. ์ด๋ ๋ง์ฝ ์ฐ์ฐ์ด ์ด๋ฏธ ์๋ฃ๋์๋ค๋ฉด
์ ๋ฉ์๋์ ๊ธฐ๋ฅ๋ค์ ์ง์ ์ฝ๋๋ก ๋ณด๊ณ ์ถ๋ค๋ฉด Future์ ๊ตฌํ์ฒด์ธ FutureTask๋ฅผ ์ดํด๋ณด๋ฉด๋๋ค.
์ค์ ๋ก ์ง๊ธ๊น์ง์ ์์๋ฅผ ๋๋ฒ๊น
ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด Future์ ๊ตฌํ์ฒด๋ก FutureTask๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ์ ์ ์๋ค.
์ด๋
CompletableFuture๊ณผ๋ ๋ณ๊ฐ์ ์ด์ผ๊ธฐ์ด๋ค. CompletableFuture๋ฅผ ์ด์ฉํ๋ค๋ฉด ๋ค๋ฅธ ๊ตฌํ์ฒด๊ฐ ์ฌ์ฉ๋๋ค.
Java๋ 1.5์ Future๋ฅผ ๋ฆด๋ฆฌ์ฆํ๊ณ , Java 8์ Future๊ณผ CompletionStage๊ฐ ๊ฒฐํฉ๋ CompletableFuture๋ฅผ ๋ฐํ๋์๋ค.
์ด๋ Future๋ง์ผ๋ก๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ฒ๋ฆฌํ๋๋ฐ ํ๊ณ๊ฐ์๋ค๋ ์๋ฏธ์ด๊ธฐ๋ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ํ์ ์ธ ํ๊ณ๋ ๋ฐ๋ก Future๊ฐ ๋น๋๊ธฐ ์ฒ๋ฆฌํ์ Callback ์คํ์ ๋ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์๋๋ค๋ ๊ฒ์ด๋ค.
๐โโ๏ธ get()์ ํธ์ถํ๋์๊ฐ ๋ธ๋กํน๋๋ค.
Future์ ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋๋ก get()๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
๋ฌธ์ ๋ ์์๋งํ๋ฏ, ์ด get()๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์๊ฐ ํด๋น ์ค๋ ๋๋ join๋ฌธ๊ณผ ์ ์ฌํ๊ฒ ๋น๋๊ธฐ๋ก ์์ฒญํ Task์ ๊ฒฐ๊ณผ๊ฐ ๋ฆฌํด๋ ๋๊น์ง ๋ธ๋กํน๋๋ค.
์ฆ, ๋น๋๊ธฐ๋ก ์์ฒญํ ์์
์ด get()์ ํธ์ถํ๊ธฐ์ ๊น์ง ๋น๋๊ธฐ/๋
ผ๋ธ๋กํน ๋ฐฉ์์ฒ๋ผ ๋์ํ๋ค, get()์ ํธ์ถํ๋์๊ฐ๋ถํฐ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๊ธฐ์ ๊น์ง ๋ธ๋กํน์ด ๋๋ ๊ฒ์ด๋ค.
๐ค ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋๋ฐฉ๋ฒ์ ๋ฌด์์ผ๊น?
๋ฐ๋ก Callback์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ์ฆ, ๋น๋๊ธฐ ์์ฒญ์ Callback ํจ์๋ ๊ฐ์ด ๋ณด๋ด๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ๋๋ฉด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๋ ์์ ์ Callback์ ์คํ๋์ด ๋น๋๊ธฐ ์์ฒญ์ ํธ์ถํ ์ค๋ ๋๊ฐ ์ ํ ๊ฒฐ๊ณผ๋ฅผ ์ํ์๊ฐ ์์ด์ง๊ธฐ์ get()์ ํธ์ถํ ํ์๊ฐ์์ด์ง๋ค.
๐โโ๏ธ FutureTask.done()์ ํ์ฉํ ์ง์ Callback ํฌํจ ๋น๋๊ธฐ ์์ฒญ ๋ง๋ค๊ธฐ
๊ทธ๋ ๋ค๋ฉด Future์ ์ฌ์ฉํด์ Callback์ ์์ ๊ตฌํํ์ง๋ชปํ๋๊ฐ?
์๋๋ค. ์ง์ ๊ตฌํํด์ ์ฌ์ฉํ๋ฉด Callback์ ์ฌ์ฉํ ์ ์๋ค.
์ค์ ๋ก Future์ ๊ธฐ๋ณธ ๊ตฌํ์ฒด์ธ FutureTask๋ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋์์๊ฒฝ์ฐ ์๋์ ๊ฐ์ด done๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
public class FutureEx_6_FutureTask_Done {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
FutureTask<String> futureTask = new FutureTask<>(() -> {
Thread.sleep(1_000);
return "Async Hello ";
}) {
// ๋น๋๊ธฐ์์
์ด ๋ชจ๋ ์ํํ๊ณ ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋. (hook ์ญํ )
@Override
protected void done() {
try {
System.out.println(get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
es.execute(futureTask);
// Future.get()์ ํธ์ถํ์ง์๋๋ค. ์ฆ, main ์ค๋ ๋๋ ์ ํ blocking๋์ง ์๋๋ค.
System.out.println("Exit");
es.shutdown();
}
}
[main]Exit
[pool-1-thread-1]Async Hello์ด๋ฅผ ํ์ฉํ๋ฉด Callback์ ํฌํจํ ๋น๋๊ธฐ ์์ฒญ์ ํ ์ ์๋ค.
์ค์ ๋ก ์ฑ๊ณต๊ณผ ์์ธ์ ๋ํ Callback์ ํฌํจํ ๋น๋๊ธฐ ์์ฒญ์ ๋ณด๋ด๋ ์์๋ฅผ ์ดํด๋ณด์.
public class FutureEx_7_FutureTask_Callback {
interface SuccessCallback {
public void onSuccess(String result);
}
interface ExceptionCallback {
public void onError(Throwable t);
}
public static class CallbackFutureTask extends FutureTask<String> {
SuccessCallback sc;
ExceptionCallback ec;
public CallbackFutureTask(Callable<String> callable, SuccessCallback sc, ExceptionCallback ec) {
super(callable);
this.sc = Objects.requireNonNull(sc);
this.ec = Objects.requireNonNull(ec);
}
// Callback ์ฒ๋ฆฌ ๋ฉ์๋.
@Override
protected void done() {
try {
// get์ด ์ฌ๊ธฐ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ ์ค๋ ๋์์ ์คํ๋๊ธฐ๋๋ฌธ์, ๊ธฐ์กด์ Main ์ค๋ ๋๋ Blocking ๋์ง ์๋๋ค.
sc.onSuccess(get());
} catch (InterruptedException e) {
// ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ์๋์ ์์ธ ์ฒ๋ฆฌ
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
// ๋น๋๊ธฐ ์์
์ค ๋ฐ์ํ ์์ธ ์ฒ๋ฆฌ.
ec.onError(e.getCause());
}
}
}
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
CallbackFutureTask callbackFutureTask = new CallbackFutureTask(() -> {
Thread.sleep(1_000);
// ์๋ฌ Callback ํ
์คํธ
// if (1==1) throw new RuntimeException("๋น๋๊ธฐ ์ฒ๋ฆฌ์ค Error!!");
return "Async Hello ";
},
s -> System.out.println("Result : " + s),
e -> System.out.println("Error : " + e.getMessage()));
es.execute(callbackFutureTask);
System.out.println("Exit");
es.shutdown();
}
}์์ ๊ฐ์ด FutureTask์ done์ ์ฌ์ฉํ์ฌ ์ฑ๊ณต๊ณผ ์๋ฌ์ ๋ํ Callback์ ์ฒ๋ฆฌํ ์ ์๋ค.
์ด๋ ํธ์ถํ๋ ์ค๋ ๋ (main ์ค๋ ๋)๋ ๋น๋๊ธฐ ์์
์ Future.get()์ ํธ์ถํ๋ ๊ฒ์ด ์๋๊ธฐ์ ๋ธ๋กํน๋์ง ์๋๋ค.
์ค์ ๋ก ํ ๋น๋์ ์ ํ๋ธ ๊ฐ์๋ฅผ๋ณด๋ฉด
CompletableFuture์ด ๋์ค๊ธฐ์ ์ ์ด๋ ๊ฒ ์ฌ์ฉํ๋ค๊ณ ํ๋ค.
๋ฌผ๋ก CompletableFuture์ ์ฌ์ฉํด๋ get()์ ํธ์ถํ๋ฉด blocking๋๋ค.
๊ทธ๋ ์ง๋ง CompletableFuture์ ๊ธฐ๋ณธ์ ์ผ๋ก Callback์ ์ง์ํ๋ค.
๋จ์ํ Callback๋ฟ๋ง ์๋๋ผ ์ฌ๋ฌ๊ฐ์ง ๋น๋๊ธฐ Task๋ฅผ ์กฐํฉํ์ฌ, ํจ๊ณผ์ ์ผ๋ก ๋น๋๊ธฐ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ง์ํ๋ค.
๋ ์์ธํ ๋ด์ฉ์ ๋ค์ ๊ธ์์ ์ ๋ฆฌํ ์์ ์ด๋ค.
์ด ๊ธ์์ Future์ ์์ฒด์ ์ธ Callback์ ์ง์ํ์ง์์ผ๋ฉฐ, ๋ค์ํ ๋น๋๊ธฐ ์์ฒญ์ ๊ฒฐ๊ณผ์ธ Future๋ฅผ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ๋ง ์ดํดํ๋ฉด๋๋ค.
- ์ปดํจํฐ ์์์ ์ญ๋ถ ํ์ฉํ๋ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ ๋์์ฑ (Concurrency)์ ๊ฝ์ด๋ผ๊ณ ๋ด๋ ์ข์ ๊ฒ ๊ฐ๋ค.
- ์ค์ ๋ก ์ด๋ฒ ๊ธ์์ ์ค๋ช ํ๋ฏ์ด, ๋๊ธฐ์ ๋นํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๋๋ฐ๋ก ์ฌ์ฉํ๋ฉด ๊ต์ฅํ ํจ๊ณผ์ ์ด๋ค.
- ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํํํ๋ ์ธํฐํ์ด์ค์ธ
Future๊ฐ ํ์ํ๋ค.Future์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ ์ ๊ทผํ ์ ์๋ ์ธํฐํ์ด์ค ์ญํ ์ ํ๋ฉฐ, ๋ค์ํ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
- ๋ค๋ง..
Future๋ฅผ ์ฌ์ฉํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ์ํดget()์ ํธ์ถํ๋ฉด ํด๋น ์ค๋ ๋๋ Blocking์ด ๊ฑธ๋ฆฌ๋ ๋ฌธ์ ๊ฐ์๋ค.- ๊ทธ๋ผ์๋ ์๋ง ํ์ฉํ๋ฉด ๋๊ธฐ๋ณด๋ค ํจ์ฌ ๋น ๋ฅธ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
get()ํธ์ถ๋ก์ธํ Blocking์ ๋ง๋ ์ข์ ๋ฐฉ๋ฒ์ Callback์ธ๋ฐFuture์ ์ด๋ฅผ ์์ฒด์ ์ผ๋ก ์ง์ํ์ง์๋๋ค.- ๋ฌผ๋ก ์ง์ ๊ตฌํํด๋๋์ง๋ง, ๊น๋ํ์ง์๋ค.
- Java 8๋ถํฐ ํจ์ํ์ด ๋ฑ์ฅํจ์๋ฐ๋ผ
CompletableFuture์ด ๋ฐํ๋์๊ณ , ์ด๋ ์์ฒด์ ์ผ๋ก Callback๊ณผ ๋น๋๊ธฐ Task๊ฐ์ ์กฐํฉ์ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋๋ก ์ง์ํ๋ค.
- https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
- https://www.youtube.com/watch?v=aSTuQiPB4Ns&list=PLOLeoJ50I1kkqC4FuEztT__3xKSfR2fpw&index=4
Task๋ฅผ ๋ง๋ค์ด ์ค๋ ๋์ ํ ๋นํ๊ธฐ ์ํด์ ๋ ์ธํฐํ์ด์ค์ค ํ๋๋ฅผ ๊ตฌํํด์ผํ๋ค.
์ฌ์ค ์ด ๋ ์ธํฐํ์ด์ค์ ์ฐจ์ด์ ์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ฝ๊ฒ ํ์ ํ ์ ์๋ค.
Runnable.java
public interface Runnalbe {
public abstract void run();
}Callable.java
public interface Callable {
V call() throws Exception;
}์ฐจ์ด์ ์ ์๋์ ๊ฐ๋ค.
- ๋ฆฌํด๊ฐ ์ ๋ฌด
Callable.call()์ Task๋ฅผ ์ฒ๋ฆฌ ํ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐํํ ์ ์๋ค. ๋ฐ๋ฉด์,Runnable.run()์ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐํํ ์ ์๋ค.
- Checked Exception ์ ๋ฌด
Callable.call()์ Checked Exception์ ๋์ง ์ ์๋ค. ๋ฐ๋ฉด์,Runnable.run()`์ Checked Exception์ ๋์ง ์ ์๋ค.- ๋ฌผ๋ก , Unchecked Exception์ ๋ ๋ค ๋์ง ์ ์๋ค.
์๊ฐ๋ณด๋ค ๋ณ๊ฑฐ ์๋ค. ๊ทธ์ Task์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ด์ผํ๋ ๊ฒฝ์ฐ
Callable์ ์ด์ฉํ๊ณ , ๊ฒฐ๊ณผ๊ฐ ํ์์๋ค๋ฉดRunnable์ ์ด์ฉํ๋ฉด ๋๋ค.
๐โโ๏ธ Executor.execute(Runnable runnable)
์ค๋ ๋ ํ์ ์ฌ์ฉํ๋ฉด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์์๋ ๊ฒฝ์ฐ Executor.execute(Runnable runnable)๋ฅผ ์ฌ์ฉํ๋ค.
execute๋ Executor์ ์ถ์ ๋ฉ์๋์ด๋ฉฐ, ์ธ์๋ก ๋์ด์ค๋ Runnable์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ๋ค.
void execute(Runnable runnable);
๋ฉ์๋์ ๊ตฌ์กฐ์์ ์ ์ ์๋ฏ์ด, ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ค๋ก ๋ฐํํ์ง ์๋๋ค.
๐โโ๏ธ ExecutorService.Submit(...)
์ค๋ ๋ ํ์ ์ฌ์ฉํ๋ฉด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ Executor.submit(...)๋ฅผ ์ฌ์ฉํ๋ค.
submit ๋ฉ์๋๋ ์๋์ ๊ฐ์ด ์๋ก ๋ค๋ฅธ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๋ ์ธ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);์ฃผ๋ชฉํ ์ ์ execute์ ๋ค๋ฅด๊ฒ submit์ ๊ฒฐ๊ณผ๊ฐ์ผ๋ก Future๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ํตํด ์๋์ ๊ฐ์ด ์ ์ถํ ์ ์๋ค.


