Skip to content

Latest commit

ย 

History

History
305 lines (219 loc) ยท 16.7 KB

Thread.md

File metadata and controls

305 lines (219 loc) ยท 16.7 KB

Thread

Thread ๋ฅผ ๋ฐฐ์šฐ๊ธฐ ์ „์—, Process ์™€ Thread ์˜ ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ํ†ตํ•ด์„œ ๋จผ์ € ๊ณต๋ถ€ํ•˜๊ณ  ์˜ค๋ฉด ์ข‹๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํ”„๋กœ์„ธ์Šค, ์“ฐ๋ ˆ๋“œ, ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์Šค, ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์ˆ™์ง€ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์„ค๋ช…ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Thread ๋ฉด์ ‘ ํฌ์ธํŠธ๋Š” ์•„๋ž˜ ๋งํฌ ์•ˆ์—์„œ ๋งŽ์ด ๋‚˜์˜ค์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ•œ๋‹ค. ๋งŒ์•ฝ์—, ํšŒ์‚ฌ์—์„œ Thread ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•ด์„œ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผํ•  ์ผ์ด ์žˆ๋‹ค๊ณ ํ•˜๋ฉด, ๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜ ์ฑ…์„ ์‚ฌ์„œ ๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

Thread ๋ž€?

Thread ์˜ ์‚ฌ์ „์  ์˜๋ฏธ๋Š” ํ•œ ๊ฐ€๋‹ฅ์˜ ์‹ค์ด๋ผ๋Š” ์˜๋ฏธ์ธ๋ฐ, ํ•œ ๊ฐ€์ง€ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์‹ค์ฒ˜๋Ÿผ ์ด์–ด ๋†“์•˜๋‹ค๊ณ  ํ•ด์„œ ์œ ๋ž˜๋œ ์ด๋ฆ„์ด๋‹ค. ์ž๋ฐ”์—์„œ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ main() ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ ์‹œ์ž‘๋˜๋Š”๋ฐ, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์˜ ๊ฒฝ์šฐ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ ๋˜๋”๋ผ๋„, ์‹คํ–‰ ์ค‘์ธ ์ž‘์—… ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ข…๋ฃŒ๋˜์ง€ ์•Š๋Š”๋‹ค.

Thread ์ƒ์„ฑ

  • Runnable ์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ–๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Thread ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
Thread thread = new Thread(Runnable target);

Runnable ์€ ์ž‘์—… ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋ผ๊ณ  ํ•ด์„œ ๋ถ™์—ฌ์ง„ ์ด๋ฆ„์ด๋‹ค.

class Task implements Runnable {
    public void run() {
        // do Something
    }
}

์œ„ ์ฝ”๋“œ๋ฅผ ๊ฐ€๋…์„ฑ ์ข‹๊ฒŒ ๋žŒ๋‹ค์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

Thread thread = new Thread(() -> {
    // do Something
});
thread.start();

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ๋„ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

Thread thread = new Thread() {
    public void run() {
         // do Something
    }
};

์Šค๋ ˆ๋“œ ์ด๋ฆ„ ์„ค์ •ํ•˜๊ธฐ

๋”ฐ๋กœ ์„ค์ •์„ ํ•˜์ง€ ์•Š์œผ๋ฉด Thread-n (n ์€ ์ˆซ์ž) ์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์„ค์ •๋œ๋‹ค.

thread.setName("์Šค๋ ˆ๋“œ ์ด๋ฆ„");

ํ˜„์žฌ ์Šค๋ ˆ๋“œ ํ™•์ธํ•˜๊ธฐ

Thread.currentThread();

๋™์‹œ์„ฑ๊ณผ ๋ณ‘๋ ฌ์„ฑ

๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ๋™์‹œ์„ฑ(Concurrency) ๋˜๋Š” ๋ณ‘๋ ฌ์„ฑ(Parallelism) ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค.

Parallelism

When two threads are running in parallel, they are both running at the same time. For example, if we have two threads, A and B, then their parallel execution would look like this:

CPU 1: A ------------------------->

CPU 2: B ------------------------->

Concurrency

When two threads are running concurrently, their execution overlaps. Overlapping can happen in one of two ways: either the threads are executing at the same time (i.e. in parallel, as above), or their executions are being interleaved on the processor, like so:

CPU 1: A -----------> B ----------> A -----------> B ---------->

๋™์‹œ์„ฑ์€ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง์— ์˜ํ•ด์„œ ์–ด๋–ค ์ˆœ์„œ๋กœ ๋™์‹œ์„ฑ์ด ์‹คํ–‰๋  ๊ฒƒ์ธ์ง€ ์ •ํ•ด์ง€๋Š”๋ฐ, ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง์— ์˜ํ•ด ์Šค๋ ˆ๋“œ๋“ค์€ ์•„์ฃผ ์งง์€ ์‹œ๊ฐ„์— ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉด์„œ ๊ทธ๋“ค์˜ ์ž‘์—…(run())์„ ์กฐ๊ธˆ์”ฉ ์‹คํ–‰ํ•œ๋‹ค.

์ž๋ฐ”์˜ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง

์ž๋ฐ”์˜ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง์€ ์šฐ์„ ์ˆœ์œ„(Priority) ๋ฐฉ์‹๊ณผ ์ˆœํ™˜ ํ• ๋‹น(Round-robin) ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ˆซ์ž๊ฐ€ ๋†’์„ ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๋‹ค. 1์ด ๊ฐ€์žฅ ๋‚ฎ๊ณ , 10์ด ๊ฐ€์žฅ ๋†’๋‹ค. ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ถ€์—ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ 5์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ํ• ๋‹น ๋ฐ›๋Š”๋‹ค.

์šฐ์„ ์ˆœ์œ„ ๋ฐฉ์‹์€ ์Šค๋ ˆ๋“œ ๊ฐ์ฒด์— ์šฐ์„ ์ˆœ์œ„ ๋ฒˆํ˜ธ๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ˆœํ™˜ ํ• ๋‹น ๋ฐฉ์‹์€ JVM ์— ์˜ํ•ด์„œ ์ •ํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์—†๋‹ค.

thread.setPriority(Thread.MAX_PRIORITY);
thread.setPriority(Thread.NORM_PRIORITY);
thread.setPriority(Thread.MIN_PRIORITY);

ExecutorService

executorservice

์ถœ์ฒ˜ : https://gompangs.tistory.com/entry/JAVA-ExecutorService-%EA%B4%80%EB%A0%A8-%EA%B3%B5%EB%B6%80

์—ฌ๊ธฐ์„œ Customer ๋ผ๋Š”๊ฑด Application ์—์„œ ํ•ด๋‹น ExecutorService ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค ์ •๋„๋กœ ํ•ด์„ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๊ณ , ํ•ด๋‹น ํด๋ž˜์Šค์—์„œ ExecutorService ์— ์ž‘์—…์„ submit ์„ ํ•˜๊ฒŒ ๋˜๋ฉด, ExecutorService ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ์ž‘์—…์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์Šค์ผ€์ฅด๋ง ํ•˜๋ฉด์„œ ์ ์ ˆํ•˜๊ฒŒ ์ผ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

Callable

Callable ์€ Runnable ์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋งŒ๋“ค์–ด์กŒ๋‹ค.

public interface Runnable {
    public void run();
}

run() ๋ฉ”์†Œ๋“œ๋Š” ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฆฌํ„ดํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, run() ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ณต์šฉ ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ํŒŒ์ดํ”„์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ›์•„์•ผ๋งŒ ํ–ˆ๋‹ค. ์ด๋Ÿฐ Runnable ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋‹จ์ ์„ ์—†์• ๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€๋œ ๊ฒƒ์ด ๋ฐ”๋กœ Callable ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

public interface Callable<V> {
    V call() throws Exception
}

Future

์ž๋ฐ” 5๋ถ€ํ„ฐ ๋ฏธ๋ž˜์˜ ์–ด๋А ์‹œ์ ์— ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š” ๋ชจ๋ธ๋กœ Future ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋‹ค. ๋น„๋™๊ธฐ ๊ณ„์‚ฐ์„ ๋ชจ๋ธ๋งํ•˜๋Š”๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์„ Future ๋‚ด๋ถ€๋กœ ์„ค์ •ํ•˜๋ฉด๋œ๋‹ค.

Ex. ๋‹จ๊ณจ ์„ธํƒ์†Œ์— ํ•œ ๋ฌด๋”๊ธฐ์˜ ์˜ท์„ ๋“œ๋ผ์ดํด๋ฆฌ๋‹ ์„œ๋น„์Šค๋ฅผ ๋งก๊ธฐ๋Š” ๋™์ž‘์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ธ์ž‘์†Œ ์ฃผ์ธ์€ ๋“œ๋ผ์ดํด๋ฆฌ๋‹์ด ์–ธ์ œ ๋๋‚ ์ง€ ์ ํžŒ ์˜์ˆ˜์ฆ(Future)๋ฅผ ์ค„ ๊ฒƒ์ด๋ฉฐ, ๋“œ๋ผ์ด๋‹ˆํด๋ฆฌ๋‹์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ์šฐ๋ฆฌ๋“ค์€ ๋‹ค๋ฅธ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Future ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ Callable ๊ฐ์ฒด ๋‚ด๋ถ€๋กœ ๊ฐ์‹ผ ๋‹ค์Œ์— ExecutorService ์— ์ œ์ถœํ•ด์•ผ ํ•œ๋‹ค.

ExecutorService

ExecutorService ๋Š” ๋ณ‘๋ ฌ์ž‘์—… ์‹œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ œ๊ณต๋˜๋Š” JAVA ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ํ†ต์ƒ์ ์œผ๋กœ ์ž‘์—…์„ ๋ถ„๋ฆฌํ•˜๊ณ  ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•˜๋ฉด Thread ๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ํ•ด๋‹น Thread ๋ฅผ ์ง์ ‘ ThreadPool ์ด ์žˆ๋‹ค๋ฉด ๋ฐ˜ํ™˜ํ•ด์ฃผ๊ฑฐ๋‚˜, ํ˜น์€ Thread ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•ด์•ผํ•œ๋‹ค.

ExecutorService ๋Š” ์‰ฝ๊ฒŒ ThreadPool ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ด๋Ÿฌํ•œ ๋ถˆํŽธํ•จ์„ ๊ฐœ์„ ํ•ด์ค€๋‹ค.

  • newFixedThreadPool(int)
    • ์ธ์ž ๊ฐœ์ˆ˜๋งŒํผ ๊ณ ์ •๋œ ์“ฐ๋ ˆ๋“œํ’€์„ ๋งŒ๋“ ๋‹ค.
  • newCachedThreadPool()
    • ํ•„์š”ํ•  ๋•Œ, ํ•„์š”ํ•œ ๋งŒํผ ์“ฐ๋ ˆ๋“œํ’€์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋ฏธ ์ƒ์„ฑ๋œ ์“ฐ๋ ˆ๋“œ๋ฅผ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ƒ์˜ ์ด์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
  • newScheduledThreadPool(int)
    • ์ผ์ • ์‹œ๊ฐ„ ๋’ค์— ์‹คํ–‰๋˜๋Š” ์ž‘์—…์ด๋‚˜, ์ฃผ๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด ScheduledThreadPool ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • newSingleThreadExecutor()
    • ์“ฐ๋ ˆ๋“œ 1๊ฐœ์ธ ExecutorService ๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ์‹ฑ๊ธ€ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์ž‘ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

์ž๋ฐ” 8 ์ด์ „์˜ ์ฝ”๋“œ

// ThreadPool ์— task ๋ฅผ ์ œ์ถœํ•˜๋ ค๋ฉด ExecutorService ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
// Callable ์„ ExecutorService ์— ์ œ์ถœํ•œ๋‹ค.
ExecutorService executor = Executors.newCachedThreadPool();
Future<Double> future = executor.submit((Callable<Double>) () -> {
    return doSomeLongComputation(); // ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•œ๋‹ค.
});

doSomethingElse(); // ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์ž‘์—… ์ˆ˜ํ–‰

try {
    // ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ํ˜ธ์ถœ ์Šค๋ ˆ๋“œ(doSomethingElse())๊ฐ€ ๋ธ”๋ก๋œ๋‹ค. 
    // ํ•˜์ง€๋งŒ ์ตœ๋Œ€ 1์ดˆ๊นŒ์ง€๋งŒ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
    Double result = future.get(1, TimeUnit.SECONDS); 
} catch (ExecutionException e) {
    // ๊ณ„์‚ฐ ์ค‘ ์˜ˆ์™ธ ๋ฐœ์ƒ
} catch (InterruptedException e) {
    // ํ˜„์žฌ ์Šค๋ ˆ๋“œ์—์„œ ๋Œ€๊ธฐ ์ค‘ ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ
} catch (TimeoutException e) {
    // Future ๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ
}

executor

์ด ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ๋ฌธ์ œ๋Š” ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ด ์˜์›ํžˆ ๋๋‚˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ, get ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋กœ๋“œํ•ด์„œ ์šฐ๋ฆฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐํ•  ์ตœ๋Œ€ ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„์„ ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

Future ์˜ ๋‹จ์ 

Future ์ธํ„ฐํŽ˜์ด์Šค๋Š” java5๋ถ€ํ„ฐ java.util.concurrency ํŒจํ‚ค์ง€์—์„œ ๋น„๋™๊ธฐ์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ์กฐํ•ฉํ•˜๊ฑฐ๋‚˜, error ํ•ธ๋“ค๋ง์„ ํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋‹จ์ ์„ ๊ฐœ์„ ํ•˜๊ณ ์ž Java 8 ์—์„œ CompletableFuture ๊ฐ€ ๋“ฑ์žฅํ–ˆ๋‹ค.

CompletableFuture

CompletableFuture ๋Š” Future ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•จ๊ณผ ๋™์‹œ์— CompletionStage ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. CompletionStage ๋Š” ๋น„๋™๊ธฐ ์—ฐ์‚ฐ Step ์„ ์ œ๊ณตํ•ด์„œ ๊ณ„์† ์ฒด์ด๋‹(Chaining) ํ˜•ํƒœ๋กœ ์กฐํ•ฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

public Future<Double> getPriceAsync(String product) {
    // ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•  CompletableFuture ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    CompletableFuture<Double> futurePrice = new CompletableFuture<>();
    new Thread(() -> {
        double price = calcaulatePrice(amount); // ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
        futurePrice.complete(price); // ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ๊ณ„์‚ฐ์ด ์™„๋ฃŒ๋˜๋ฉด Future ์— ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.
    }).start();
    return futurePrice; // ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๊ฐ€ ์™„๋ฃŒ๋˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  Future ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
}

ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Shop shop = new Shop("BestShop");
long start = System.nanoTime();
Future<Double> futurePrice = shop.getPriceAsync("my favorite product"); // ์ƒ์ ์— ์ œํ’ˆ ๊ฐ€๊ฒฉ ์š”์ฒญ
long invocationTime = ((System.nanoTime() - start) / 1_000_000); 
System.out.println("Invocation returned after " + invocationTime + " msecs");

// ์ œํ’ˆ์˜ ๊ฐ€๊ฒฉ์„ ๊ณ„์‚ฐํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์ƒ์  ๊ฒ€์ƒ‰ ๋“ฑ ๋‹ค๋ฅธ ์ž‘์—… ์ˆ˜ํ–‰
doSomethingElse();

try {
    double price = futurePrice.get(); // ๊ฐ€๊ฒฉ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด Future ์—์„œ ๊ฐ€๊ฒฉ ์ •๋ณด๋ฅผ ์ผ๊ณ , ๊ฐ€๊ฒฉ ์ •๋ณด๊ฐ€ ์—†์œผ๋ฉด ๊ฐ€๊ฒฉ ์ •๋ณด๋ฅผ ๋ฐ›์„ ๋•Œ ๊นŒ์ง€ ๋ธ”๋กํ•œ๋‹ค.
    System.out.println("Price is %.2f%n", price);
} catch (Exception e) {
    throw new RuntimeExceptione(e);
}
long retrievalTime = ((System.nanoTime() - start) / 1_000_000);
System.out.println("Price returned after " + retrievalTime + " msecs");

์ƒ์ ์€ ๋น„๋™๊ธฐ API ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ์ฆ‰์‹œ Future๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฐ˜ํ™˜๋œ Future ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‚˜์ค‘์— ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ์‚ฌ์ด ํด๋ผ์ด์–ธํŠธ๋Š” ๋‹ค๋ฅธ ์ƒ์ ์— ๊ฐ€๊ฒฉ ์ •๋ณด๋ฅผ ์š”์ฒญํ•˜๋Š” ๋“ฑ ์ฒซ ๋ฒˆ์งธ ์ƒ์ ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉด์„œ ๋Œ€๊ธฐํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Future vs CompletableFuture

ExecutorService vs CompletableFuture

  • ์„œ๋กœ ์ œ๊ณตํ•˜๋Š” API ๊ฐ€ ๋‹ค๋ฅด๋‹ค.
  • ๋น„๋™๊ธฐ๋ฅผ ์ง€์›ํ•œ๋‹ค๋Š” ์ ์€ ๋™์ผํ•˜๋‹ค.
  • ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ์ง€์›ํ•œ๋‹ค๋Š” ์ ์—์„œ CompletableFuture ๊ฐ€ ๊ฐ€๋…์„ฑ์ด ๋” ์ข‹๋‹ค.

https://stackoverflow.com/questions/52303472/executorservice-vs-completablefuture

Sync, Async, Blocking, Non-Blocking

  • async
    • ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ณ  ์š”์ฒญ ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ์‹คํ–‰
    • ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์Œ
  • sync
    • ์ด๋ฒคํŠธ๋ฅผ ์ž์‹ ์ด ์ง์ ‘ ์ฒ˜๋ฆฌ(ํ™•์ธ์˜ ์ฃผ์ฒด๊ฐ€ ์œ ์ € ํ”„๋กœ์„ธ์Šค์ด๋ฉฐ, ๋‹ค ๋ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฑฐ๋‚˜ ์Šค์Šค๋กœ ํ™•์ธ)
    • ๋ฉ”์†Œ๋“œ,์ž‘์—…๋“ฑ์„ ์‹คํ–‰ํ•˜๊ณ  ํ•ด๋‹น ๋ฉ”์†Œ๋“œ์˜ ๊ฒฐ๊ณผ๋ฅผ ์–ป์–ด์˜ฌ ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐฉ์‹
  • block
    • ์™„๋ฃŒ๊นŒ์ง€ ๋Œ€๊ธฐ(๋ฆฌํ„ด๋˜๊ธฐ ์ „๊นŒ์ง€ ๋ฉˆ์ถค)
  • non-block
    • ๋ฏธ์™„๋ฃŒ๋ผ๋„ ์ฆ‰์‹œ ๋ฆฌํ„ด

๋™๊ธฐ API vs ๋น„๋™๊ธฐ API

  • ๋™๊ธฐ API
    • ๋™๊ธฐ API ์—์„œ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ณ„์‚ฐ์„ ์™„๋ฃŒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜๋˜๋ฉด ํ˜ธ์ถœ์ž๋Š” ๋ฐ˜ํ™˜๋œ ๊ฐ’์œผ๋กœ ๊ณ„์† ๋‹ค๋ฅธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด์ฒ˜๋Ÿผ ํ˜ธ์ถœ์ž๋Š” ํ”ผํ˜ธ์ถœ์ž์˜ ์ž‘์—… ์™„๋ฃŒ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ, ๋™๊ธฐ API ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์„ ๋ธ”๋ก ํ˜ธ์ถœ(blocking call)์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • ๋น„๋™๊ธฐ API
    • ๋น„๋™๊ธฐ API ์—์„œ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ฆ‰์‹œ ๋ฐ˜ํ™˜๋˜๋ฉฐ ๋๋‚ด์ง€ ๋ชปํ•œ ๋‚˜๋จธ์ง€ ์ž‘์—…์„ ํ˜ธ์ถœ์ž ์Šค๋ ˆ๋“œ์™€ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ํ• ๋‹นํ•œ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋น„๋™๊ธฐ API ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์„ ๋น„๋ธ”๋ก ํ˜ธ์ถœ(non-blocking call) ์ด๋ผ๊ณ  ํ•œ๋‹ค.

Blocking I/O vs Non-Blocking I/O

non-blocking API๋Š” ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋œ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ํ†ต์ง€ํ• ๊นŒ?

  • non-blocking API ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ˜ธ์ถœ์ธก์€ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋Š”๊ฒƒ์„ ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผํ•œ๋‹ค.
  • ํ˜ธ์ถœ์ธก์€ ์–ด๋–ป๊ฒŒ ์•Œ๊ฒŒ๋ ๊นŒ?
  • CPU ๋Š” ์ธ์ŠคํŠธ๋Ÿญ์…˜(๋ช…๋ น์–ด)์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋Š”๊ฒƒ์„ ํ†ต์ง€ํ• ๊นŒ?
  • ์šด์˜์ฒด์ œ ready queue ์— ๋“ค์–ด๊ฐ€์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์‘๋‹ต์„ ํ•œ๋‹ค. ๋ฐ”๋กœ ์‘๋‹ตํ•˜๊ธฐ ํž˜๋“ ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ ์ •์ƒ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ๊ณ„์†ํ•ด์„œ ์š”์ฒญ์„ ๋‹ค์‹œ ๋ณด๋‚ธ๋‹ค.
  • blocking ๋ฐฉ์‹์˜ ๋น„ํšจ์œจ์ ์ธ ๋ถ€๋ถ„์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ non-blocking ์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ๊ณ„์†ํ•ด์„œ ์š”์ฒญ์„ ๋‹ค์‹œ ๋ณด๋‚ด๋ฉด์„œ ์ž์›์„ ๋‚ญ๋น„ํ•˜๊ฒŒ ๋œ๋‹ค(์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒ)

์ด๋ฒคํŠธ ํ†ต์ง€ ๋ชจ๋ธ

๋งค๋ฒˆ ํ˜ธ์ถœ์ธก์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ค€๋น„๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š”๊ฒƒ์„ ๋น„ํšจ์œจ์ ์ด๋‹ค. ์ˆ˜์‹  ๋ฒ„ํผ๋‚˜ ์ถœ๋ ฅ ๋ฒ„ํผ์ธก์—์„œ ์ด๋ฒคํŠธ๋กค ํ†ต์ง€ํ•˜๋ฉด ์–ด๋–จ๊นŒ? I/O ์ž‘์—… ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋™๊ธฐ,๋น„๋™๊ธฐ ๋ชจ๋ธ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Synchronous Model
    • I/O ์ž‘์—…์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ์œ ์ € ํ”„๋กœ์„ธ์Šค๋Š” ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹
    • notify ๋ฅผ ์œ ์ € ํ”„๋กœ์„ธ์Šค(ํ˜ธ์ถœ์ธก)์ด ๋‹ด๋‹นํ•˜์—ฌ ์ฃผ์ฒด์ ์œผ๋กœ ์ง„ํ–‰ํ•˜๋ฉด ์ปค๋„์€ ์œ ์ € ํ”„๋กœ์„ธ์Šค์˜ ์š”์ฒญ์— ์ˆ˜๋™์ ์„ ์‘๋‹ตํ•œ๋‹ค.
  • Asynchronous Model
    • I/O ์ž‘์—…์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ์œ ์ € ํ”„๋กœ์„ธ์Šค ๋Š” ์ž์‹ ์˜ ์ผ์„ ํ•˜๋‹ค๊ฐ€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์˜ํ•ด ์•Œ๋ฆผ์ด ์˜ค๋ฉด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
    • notify ๋ฅผ ์ปค๋„์ด ๋‹ด๋‹นํ•˜์—ฌ ์ฃผ์ฒด์ ์œผ๋กœ ์ง„ํ–‰(์ฝœ๋ฐฑ์„ ๋„˜๊ฒจ์ฃผ๋Š” ํ˜•ํƒœ)ํ•˜๊ณ  ํ˜ธ์ถœ์ธก์€ ์ˆ˜๋™์ ์ธ ์ž…์žฅ์—์„œ ํ†ต์ง€๊ฐ€ ์˜ค๋ฉด ๊ทธ๋•Œ I/O ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ ๋ฐ›๋Š”๋‹ค.

Non-Blocking I/O ๋Š” ๋‚ด๋ถ€์—์„œ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋ ๊นŒ?

  • ๋Œ€๋ถ€๋ถ„์˜ non-blocking ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์€ ๋ฌดํ•œ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ์‘๋‹ต๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์ง€์†์ ์œผ๋กœ ํ™•์ธํ•œ๋‹ค.(poll) ์ด๋ฅผ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
    • ์ฆ‰, ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ํ†ตํ•ด์„œ socket ์—์„œ ์ฝ์„ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€ ๊ณ„์† ํ™•์ธํ•œ๋‹ค.
  • ๋ฆฌ๋ˆ…์Šค epoll, io_uring (์ž๋ฐ” NIO์—์„œ ์œˆ๋„์šฐ๋Š” select, ๋งฅ์€ kqueue, ๋ฆฌ๋ˆ…์Šค๋Š” epoll์„ ์ง€์›)

References