Skip to content

Latest commit

ย 

History

History
769 lines (528 loc) ยท 31.7 KB

File metadata and controls

769 lines (528 loc) ยท 31.7 KB

๋ชฉ์ฐจ



์ž๋ฐ” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์™€ Future

๋น„๋™๊ธฐ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์ค‘์š”์„ฑ์€ ๋‚˜๋‚ ์ด ์ปค์ง€๊ณ ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ๋Š” ์ปดํ“จํ„ฐ ๋ฐœ์ „์— ๋”ฐ๋ผ ๋น„๋™๊ธฐ๋ž€ ๊ฐœ๋…์„ ๋ชจ๋ฅด๊ณ ์„  ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์—†์„์ •๋„๊ฐ€ ๋˜์—ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์€ ์ž๋ฐ” ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋ฅผ ์ •๋ฆฌํ•˜๋Š” ์‹œ๋ฆฌ์ฆˆ์˜ ์ฒซ๋ฒˆ์งธ ๊ธ€์ด๋‹ค.

์ž๋ฐ” ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์—ญ์‚ฌ์—๋”ฐ๋ผ JDK 1.5์— ๋ฐœํ‘œ๋œ Future์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์ด์•ผ๊ธฐํ•ด๋ณธ๋‹ค.

๊ธ€ ์‹œ์ž‘๋ถ€ํ„ฐ Future๋ž€ ๋ฌด์—‡์ด๋ฉฐ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค ๋‹ค๋ฅธ ๊ธ€๋„ ๋งŽ์œผ๋ฏ€๋กœ, ์ด๋ฒˆ ๊ธ€์€ Future๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€ ๊ทธ๋ฆฌ๊ณ  ๋ฌด์—‡์ด ์ข‹์€์ง€ ์•Œ์•„๋ณธ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Future์˜ ํ•œ๊ณ„์™€ ์ œ๋Œ€๋กœ๋œ ๋น„๋™๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ ํž˜๋“  ์ด์œ ๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ, ๋‹ค์Œ์œผ๋กœ ๋‚˜์˜จ ๋น„๋™๊ธฐ ํ”„๋ ˆ์ž„์›Œํฌ์ธ CompletableFuture ๋‚ด์šฉ์˜ ๋ฐ‘๋ฐฅ์„ ๊น”์•„๋ณด๋ ค๊ณ ํ•œ๋‹ค.

์ด๋ฒˆ ๊ธ€์˜ ๋‚ด์šฉ์€ ํ•„์ž๊ฐ€ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜๋ฉฐ ์ดํ•ดํ•œ ๋‚ด์šฉ์€ ์ •๋ฆฌํ•œ ๊ฒƒ์ด๋‹ค. ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.


1 ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ ์ฝ”๋“œ

์šฐ์„  ๋ณธ๊ฒฉ์ ์œผ๋กœ Future์„ ์•Œ์•„๋ณด๊ธฐ์— ์•ž์„œ ์ž๋ฐ”๋ฅผ ์ด์šฉํ•˜์—ฌ ๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.


1-1 ๋™๊ธฐ ์ฝ”๋“œ

๋™๊ธฐ (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

์‹คํ–‰ ์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. 3์ดˆ sleep์ดํ›„ Start ์ถœ๋ ฅ
  2. Start๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ ๋‚˜์„œ 2์ดˆ sleep์ดํ›„ In Progress ์ถœ๋ ฅ
  3. In Progress๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ ๋‚˜์„œ 1์ดˆ sleep์ดํ›„ End ์ถœ๋ ฅ

์‹คํ–‰๊ฒฐ๊ณผ์™€ ์ˆœ์„œ๋ฅผ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ์—์„œ ๋‘ ๊ฐœ์˜ Print๊ฐ€ ๋™๊ธฐ/๋ธ”๋กœํ‚น ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

์–ด๋–ค๊ฐ€? ๊ต‰์žฅํžˆ ๊ฐ„๋‹จํ•˜๋ฉฐ, ์ง๊ด€์ ์ด๊ณ  ์ดํ•ดํ•˜๊ธฐ๋„ ์‰ฝ๋‹ค.


โ—๏ธ ํ•˜์ง€๋งŒ ๋™๊ธฐ๋ฐฉ์‹์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ๊ฐ์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ์ฃผ์–ด์งˆ ๋•Œ๊นŒ์ง€ ์•„๋ฌด๊ฒƒ๋„ ๋ชปํ•˜๊ณ  ๋Œ€๊ธฐํ•ด์•ผํ•˜๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.


์ด 6์ดˆ์˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค.

์ง€๊ธˆ์€ ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ํŠน์ • ํ…์ŠคํŠธ๋ฅผ ๋ช‡์ดˆํ›„์— ์ถœ๋ ฅํ•˜๋Š” ์˜ˆ์‹œ์ด์ง€๋งŒ,

๋งŒ์•ฝ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ์•ˆ์—์„œ ๋™๊ธฐ์ ์œผ๋กœ ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€์ผ์„ ์‹คํ–‰ํ•˜๋ฉด ์ฒ˜๋ฆฌ์‹œ๊ฐ„์ด ์„ ํ˜•์ ์œผ๋กœ ๋Š˜์–ด๋‚  ์ˆ˜ ๋ฐ–์—์—†๋‹ค. - ์ค‘์š”

์ด๊ฒŒ ๋ฐ”๋กœ ๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ด๋ฉฐ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฐฉ์‹์ด ํ•„์š”ํ•œ ์ด์œ ์ด๊ธฐ๋„ํ•˜๋‹ค.

์ •ํ™•ํžˆํ•˜์ž๋ฉด ์œ„ ๋ฐฉ์‹์€ ๋™๊ธฐ/๋ธ”๋กœํ‚น์ด๋‹ค.


1-2 ๋น„๋™๊ธฐ ์ฝ”๋“œ

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„ ์˜ˆ์‹œ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ๋น„๋™๊ธฐ๋กœ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

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

์‹คํ–‰ ์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. Start, Process, End ์ˆœ์œผ๋กœ 3์ดˆ, 2์ดˆ, 1์ดˆ๋ฅผ sleepํ•˜๊ณ  ํ…์ŠคํŠธ๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ๋น„๋™๊ธฐ๋กœ ์š”์ฒญํ•œ๋‹ค.
  2. ๊ฐ ์ž‘์—…์€ ์ฃผ์–ด์ง„ ์‹œ๊ฐ„๋งŒํผ sleepํ•˜๊ณ  ํ…์ŠคํŠธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ๋ˆˆ์—ฌ๊ฒจ๋ด์•ผํ•  ๋ถ€๋ถ„์€ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ End์ด ๋จผ์ € ์ถœ๋ ฅ๋˜๊ณ , ๊ทธ ๋‹ค์Œ Process, ๋งˆ์ง€๋ง‰์œผ๋กœ Start๊ฐ€ ์ถœ๋ ฅ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋˜ํ•œ, 6์ดˆ ๊ฑธ๋ฆฌ๋˜ ๋ชจ๋“  ์ž‘์—…์ด 3์ดˆ๋งŒ์— ๋๋‚ฌ๋‹ค.

์ด๋ฅผ ๊ทธ๋ฆผ์œผ๋กœ ๊ทธ๋ ค๋ณด๋ฉด ์•„๋ž˜์™€๊ฐ™๋‹ค.


์ด 3์ดˆ์˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋œ๋‹ค.

๊ทธ๋ฆผ์—์„œ๋„ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ๋น„๋™๊ธฐ๋Š” ๋™๊ธฐ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ CPU ์ž์›๋“ค์„ ์ตœ๋Œ€ํ•œ ์‚ฌ์šฉํ•ด์„œ idle(๋†€๊ณ ์žˆ๋Š”)ํ•œ ์ž‘์—…์ด ์—†๋„๋กํ•จ์œผ๋กœ์จ ๊ฐ™์€ ์ž‘์—…์ด๋ผ๋„ ๋” ๋น ๋ฅด๊ฒŒ ์ž‘์—…์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฒŒ ๋ฐ”๋กœ ๋น„๋™๊ธฐ๊ฐ€ ์ข‹์€ ๊ฐ€์žฅ ํฐ ์ด์œ ์ด๊ธฐ๋„ํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ •ํ™•ํžˆํ•˜์ž๋ฉด ์œ„ ๋ฐฉ์‹์€ ๋น„๋™๊ธฐ/๋…ผ๋ธ”๋กœํ‚น์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์•„ํ•˜! ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์˜ ์ž‘์—… ์™„๋ฃŒ๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜๊ฐ€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋น„๋™๊ธฐ๊ตฌ๋‚˜! ๊ทธ๋ฆฌ๊ณ  ํ˜ธ์ถœํ•˜๊ณ  ๋ฐ”๋กœ ๋ฆฌํ„ด๋ฐ›์œผ๋‹ˆ ๋…ผ๋ธ”๋กœํ‚น์ด๊ตฌ๋‚˜!๋ฅผ ์ดํ•ดํ•ด์•ผํ•œ๋‹ค.

๋งŒ์•ฝ ์ดํ•ด๊ฐ€ ์•ˆ๋œ๋‹ค๋ฉด 4๊ฐ€์ง€์˜ I/O ๋ฐฉ์‹์˜ ์ฐจ์ด์ ์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ ์˜ค๋Š”๊ฒŒ ์ข‹๋‹ค.

๊ทธ๋ ‡๋‹ค๊ณ  ๋ฌด์กฐ๊ฑด ๋น„๋™๊ธฐ ๋ฐฉ์‹์ด ์ข‹์€ ๊ฒƒ๋งŒ์€ ์•„๋‹ˆ๋‹ค. ์ œ๋Œ€๋กœ ์•Œ๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ œ๋Œ€๋กœ ๋ชจ๋ฅด๋ฉด ์˜คํžˆ๋ ค ์—ญํšจ๊ณผ๊ฐ€ ๋‚  ์ˆ˜ ์žˆ๋‹ค.


2 Future์˜ ์—ญํ•  - ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค

์•ž์„œ ๊ฐ„๋‹จํ•œ ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ์ฝ”๋“œ๋กœ ๋น„๋™๊ธฐ๊ฐ€ ์–ด๋–ค ์ ์—์„œ ์ข‹์€์ง€ ์•Œ์•„๋ณด์•˜๋‹ค.

๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•˜์ž๋ฉด, ๋น„๋™๊ธฐ ๋ฐฉ์‹์€ ๋™์‹œ์„ฑ์„ ํ™œ์šฉํ•˜์—ฌ CPU ์ž์›์„ ์ตœ๋Œ€ํ•œ์œผ๋กœ ํ™œ์šฉํ•˜์—ฌ ๋” ๋น ๋ฅด๊ฒŒ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ๋„ ๋ฌผ๋ก  ๋‹จ์ ์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ์ธกํ•˜๊ธฐํž˜๋“ค๊ณ , ์ž˜๋ชป์‚ฌ์šฉํ•˜๋ฉด CPU ์‚ฌ์šฉ๋Ÿ‰์ด ๊ต‰์žฅํžˆ ์ฆ๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๊ธฐ์— ๋น„๋™๊ธฐ ๋กœ์ง์„ ๊ตฌ์„ฑํ•  ๋• ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฐฉ์‹๊ณผ Flow๋ฅผ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์ข‹๋‹ค.

์ด๋ฒˆ ์žฅ์—” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฐฉ์‹์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ์œ„ํ•ด ๊ผญ ์•Œ์•„์•ผํ•˜๋Š” ๋น„๋™๊ธฐ Task ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์—๋Œ€ํ•ด์„œ ์•Œ์•„๋ณธ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด Future๊ฐ€ ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณธ๋‹ค.


๐Ÿ’โ€โ™‚๏ธ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์—๋Š” ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  1. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ
  2. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ

์œ„์—์„œ ์‚ดํŽด๋ณธ ๊ฐ„๋‹จํ•œ ๋น„๋™๊ธฐ ์˜ˆ์‹œ๋Š” ์‚ฌ์‹ค ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ์ด๋‹ค.

๋‹ค์‹œ๋งํ•ด, Start, Process, End๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฒ˜๋ฆฌ์€ ์„œ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์ „ํ˜€์—†์œผ๋ฉฐ, ๋™์‹œ๊ฐ„์— ์„œ๋กœ์˜ ์ž‘์—… ์™„๋ฃŒ ์—ฌ๋ถ€๊ฐ€ ์—ฐ๊ด€์—†์œผ๋ฏ€๋กœ ์„œ๋กœ์˜ ์ผ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ…์ŠคํŠธ๋กœ๋งŒ ๋งํ•˜๋ฉด ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ํž˜๋“œ๋‹ˆ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ์™€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋ฅผ ์˜ˆ์‹œ๋ฅผํ†ตํ•ด ์‚ดํŽด๋ณด์ž.


2-1 ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ - execute

๐Ÿ’โ€โ™‚๏ธ ๋จผ์ € ์œ„์—์„œ ์‚ดํŽด๋ณธ ๋™์ผํ•œ ์˜ˆ์‹œ ๋งˆ์ง€๋ง‰์— 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 (๋ณ‘ํ–‰) ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด๋‹ค.


2-2 ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ - submit๊ณผ Future

์œ„์™€ ๊ฐ™์ด ๋น„๋™๊ธฐ/๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์œผ๋กœ๋งŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋“ค์€ ํ–‰๋ณตํ•˜๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ ํ˜„์‹ค์—์„  ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์š”์ฒญํ•˜๋˜ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ํ›จ์”ฌ ๋งŽ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ์„ ์กฐ๊ธˆ ๋” ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‚ดํŽด๋ณด์ž.


๐Ÿค” ๋งŒ์•ฝ 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

์‹คํ–‰ ์ˆœ์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. main ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ๊ฐ ์ฃผ์–ด์ง„ ์‹œ๊ฐ„๋งŒํผ sleepํ•˜๊ณ  Start, Process, End๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Task (์ฒ˜๋ฆฌ)์„ ์Šค๋ ˆ๋“œ ํ’€์— ์š”์ฒญํ•œ๋‹ค.
    • ์ด๋•Œ, main์€ ๋…ผ๋ธ”๋กœํ‚น์œผ๋กœ ์š”์ฒญํ•œ๋‹ค. ์ฆ‰, ์ œ์–ด๊ถŒ์„ main์—๊ฒŒ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  2. main์€ ์ž์‹ ์˜ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋‹ค, ๋น„๋™๊ธฐ๋กœ ์š”์ฒญํ•œ Task์˜ ๊ฒฐ๊ณผ๋“ค์„ ์–ป๊ธฐ์œ„ํ•ด Future.get()์„ ์š”์ฒญํ•œ๋‹ค.
    • ์ดํ›„์— ์–˜๊ธฐํ•˜๊ฒ ์ง€๋งŒ, ์ด๋•Œ main์€ ๋น„๋™๊ธฐ๋กœ ์š”์ฒญํ•œ Task๊ฐ€ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ์ „๊นŒ์ง€ ๋ธ”๋กœํ‚น๋œ๋‹ค.
  3. 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๋œ๋‹ค.


3 Future

์•ž์„œ ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ด๋ฉฐ, Future๊ฐ€ ์–ด๋–ค ์—ญํ• ์„ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด์•˜๋‹ค.

์ด๋ฒˆ ์žฅ์—์„  Future์˜ ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…์„ ์ •๋ฆฌํ•  ์˜ˆ์ •์ด๋‹ค.

์ด๋ฒˆ ์žฅ์˜ ๋‚ด์šฉ์€ ์‚ฌ์‹ค ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ์—๋„ ๋งŽ์œผ๋ฏ€๋กœ ์Šคํ‚ตํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.


3-1 Future๋ž€ - pending completion

๐Ÿ’โ€โ™‚๏ธ Future๋ž€ - pending completion

  • Java 1.5๋ถ€ํ„ฐ ๋‚˜์˜จ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋น„๋™๊ธฐ ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
    • ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ฒ˜๋ฆฌ ์™„๋ฃŒ๋ฅผ ๊ธฐ๋‹ค๋ ค์„œ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • Future๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์ฒ˜๋ฆฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Future์€ ๋‚ด๋ถ€์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜๋‹ค.
    • ๊ตณ์ด synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š์•„๋„๋œ๋‹ค.
  • Future์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ๋•Œ๋ฌธ์—, ์ง€์—ฐ ์™„๋ฃŒ (pending completion)์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฐ๋‹ค.

3-2 Future์˜ ์—ญํ• 

๐Ÿ’โ€โ™‚๏ธ 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๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.


4 Future์˜ ํ•œ๊ณ„ - Callback ๋ถ€์žฌ

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๊ฐ„์˜ ์กฐํ•ฉ์„ ์‰ฝ๊ฒŒ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•œ๋‹ค.

์ฐธ๊ณ 


๊ทธ์™ธ - Runnable vs Callable

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์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.


๊ทธ์™ธ - execute()์™€ submit()

๐Ÿ’โ€โ™‚๏ธ 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๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋‹ค.