Thread ๋ฅผ ๋ฐฐ์ฐ๊ธฐ ์ ์, Process ์ Thread ์ ๊ฐ๋ ์ ๋ํด์ ์๋์ ๋งํฌ๋ฅผ ํตํด์ ๋จผ์ ๊ณต๋ถํ๊ณ ์ค๋ฉด ์ข๋ค. ์๋ํ๋ฉด ์ด๋ฒ ๊ธ์์๋ ํ๋ก์ธ์ค, ์ฐ๋ ๋, ๋ฉํฐ ํ๋ก์ธ์ค, ๋ฉํฐ ์ฐ๋ ๋์ ๋ํ ๊ฐ๋ ์ ์์งํ๋ค๊ณ ๊ฐ์ ํ๊ณ ์ค๋ช ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
Thread ๋ฉด์ ํฌ์ธํธ๋ ์๋ ๋งํฌ ์์์ ๋ง์ด ๋์ค์ง ์์๊น ์๊ฐํ๋ค. ๋ง์ฝ์, ํ์ฌ์์ Thread ๋ฅผ ์ง์ ์์ฑํด์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํด์ผํ ์ผ์ด ์๋ค๊ณ ํ๋ฉด,
๋ชจ๋ ์๋ฐ ์ธ ์ก์
์ฑ ์ ์ฌ์ ๋ณด๋ ๊ฒ์ ์ถ์ฒํ๋ค.
Thread ์ ์ฌ์ ์ ์๋ฏธ๋ ํ ๊ฐ๋ฅ์ ์ค
์ด๋ผ๋ ์๋ฏธ์ธ๋ฐ, ํ ๊ฐ์ง ์์
์ ์คํํ๊ธฐ ์ํด ์์ฐจ์ ์ผ๋ก ์คํํ ์ฝ๋๋ฅผ ์ค์ฒ๋ผ ์ด์ด ๋์๋ค๊ณ ํด์ ์ ๋๋ ์ด๋ฆ์ด๋ค.
์๋ฐ์์๋ ๋ฉ์ธ ์ค๋ ๋๊ฐ main() ๋ฉ์๋๋ฅผ ์คํํ๋ฉด์ ์์๋๋๋ฐ, ๋ฉํฐ ์ค๋ ๋์ ๊ฒฝ์ฐ ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ข
๋ฃ ๋๋๋ผ๋, ์คํ ์ค์ธ ์์
์ค๋ ๋๊ฐ ํ๋๋ผ๋ ์์ผ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ด ์ข
๋ฃ๋์ง ์๋๋ค.
- 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) ์ผ๋ก ์คํ๋๋ค.
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 ------------------------->
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);
์ถ์ฒ : 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 ์ Runnable ์ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด์ ๋ง๋ค์ด์ก๋ค.
public interface Runnable {
public void run();
}
run() ๋ฉ์๋๋ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฆฌํดํ์ง ์๊ธฐ ๋๋ฌธ์, run() ๋ฉ์๋์ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌํ๊ธฐ ์ํด์๋ ๊ณต์ฉ ๋ฉ๋ชจ๋ฆฌ๋ ํ์ดํ์ ๊ฐ์ ๊ฒ๋ค์ ์ฌ์ฉํด์ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐ์์ผ๋ง ํ๋ค. ์ด๋ฐ Runnable ์ธํฐํ์ด์ค์ ๋จ์ ์ ์์ ๊ธฐ ์ํด ์ถ๊ฐ๋ ๊ฒ์ด ๋ฐ๋ก Callable ์ธํฐํ์ด์ค์ด๋ค.
public interface Callable<V> {
V call() throws Exception
}
์๋ฐ 5๋ถํฐ ๋ฏธ๋์ ์ด๋ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๋ ๋ชจ๋ธ๋ก Future
์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๊ณ ์๋ค. ๋น๋๊ธฐ ๊ณ์ฐ์ ๋ชจ๋ธ๋งํ๋๋ฐ ์ฃผ๋ก ์ฌ์ฉ๋๋ฉฐ, ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์๋ ์์
์ Future ๋ด๋ถ๋ก ์ค์ ํ๋ฉด๋๋ค.
Ex. ๋จ๊ณจ ์ธํ์์ ํ ๋ฌด๋๊ธฐ์ ์ท์ ๋๋ผ์ดํด๋ฆฌ๋ ์๋น์ค๋ฅผ ๋งก๊ธฐ๋ ๋์์ ๋น์ ํ ์ ์๋ค. ์ธ์์ ์ฃผ์ธ์ ๋๋ผ์ดํด๋ฆฌ๋์ด ์ธ์ ๋๋ ์ง ์ ํ
์์์ฆ(Future)
๋ฅผ ์ค ๊ฒ์ด๋ฉฐ, ๋๋ผ์ด๋ํด๋ฆฌ๋์ด ์งํ๋๋ ๋์ ์ฐ๋ฆฌ๋ค์ ๋ค๋ฅธ ์ผ์ ํ ์ ์๋ค.
Future ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ Callable
๊ฐ์ฒด ๋ด๋ถ๋ก ๊ฐ์ผ ๋ค์์ ExecutorService
์ ์ ์ถํด์ผ ํ๋ค.
ExecutorService ๋ ๋ณ๋ ฌ์์ ์ ์ฌ๋ฌ๊ฐ์ ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ ๊ณต๋๋ JAVA ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค. ํต์์ ์ผ๋ก ์์ ์ ๋ถ๋ฆฌํ๊ณ ์ํํ๋ ์์ ์ ์ง์ ๊ตฌํํ๊ณ ์ ํ๋ฉด Thread ๋ฅผ ์์ฑํด์ ์์ ์ ์ฒ๋ฆฌํ๊ณ , ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ํด๋น Thread ๋ฅผ ์ง์ ThreadPool ์ด ์๋ค๋ฉด ๋ฐํํด์ฃผ๊ฑฐ๋, ํน์ Thread ๋ฅผ ์ ๊ฑฐํ๋ ์์ ์ ์งํํด์ผํ๋ค.
ExecutorService ๋ ์ฝ๊ฒ ThreadPool ์ ๊ตฌํํ ์ ์์ด์ ์ด๋ฌํ ๋ถํธํจ์ ๊ฐ์ ํด์ค๋ค.
- newFixedThreadPool(int)
- ์ธ์ ๊ฐ์๋งํผ ๊ณ ์ ๋ ์ฐ๋ ๋ํ์ ๋ง๋ ๋ค.
- newCachedThreadPool()
- ํ์ํ ๋, ํ์ํ ๋งํผ ์ฐ๋ ๋ํ์ ์์ฑํ๋ค. ์ด๋ฏธ ์์ฑ๋ ์ฐ๋ ๋๋ฅผ ์ฌํ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์์ ์ด์ ์ด ์์ ์ ์๋ค.
- newScheduledThreadPool(int)
- ์ผ์ ์๊ฐ ๋ค์ ์คํ๋๋ ์์ ์ด๋, ์ฃผ๊ธฐ์ ์ผ๋ก ์ํ๋๋ ์์ ์ด ์๋ค๋ฉด ScheduledThreadPool ์ ๊ณ ๋ คํด๋ณผ ์ ์๋ค.
- newSingleThreadExecutor()
- ์ฐ๋ ๋ 1๊ฐ์ธ ExecutorService ๋ฅผ ๋ฆฌํดํ๋ค. ์ฑ๊ธ ์ฐ๋ ๋์์ ๋์ํด์ผ ํ๋ ์์ ์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค.
// 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 ๊ฐ ์๋ฃ๋๊ธฐ ์ ์ ํ์์์ ๋ฐ์
}
์ด ์๋๋ฆฌ์ค์ ๋ฌธ์ ๋ ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ด ์์ํ ๋๋์ง ์์ผ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์, get ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ก๋ํด์ ์ฐ๋ฆฌ ์ค๋ ๋๊ฐ ๋๊ธฐํ ์ต๋ ํ์์์ ์๊ฐ์ ์ ํ๋ ๊ฒ์ด ์ข๋ค.
Future ์ธํฐํ์ด์ค๋ java5๋ถํฐ java.util.concurrency ํจํค์ง์์ ๋น๋๊ธฐ์ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐ๋ ์ฉ๋๋ก ์ฌ์ฉํ๋ค. ํ์ง๋ง ๋น๋๊ธฐ์ ๊ฒฐ๊ณผ๊ฐ์ ์กฐํฉ
ํ๊ฑฐ๋, error ํธ๋ค๋ง
์ ํ ์๊ฐ ์์๋ค.
์ด๋ฌํ ๋จ์ ์ ๊ฐ์ ํ๊ณ ์ Java 8 ์์ 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 ๋ฅผ ์ด์ฉํ์ฌ ๋์ค์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค. ๊ทธ ์ฌ์ด ํด๋ผ์ด์ธํธ๋ ๋ค๋ฅธ ์์ ์ ๊ฐ๊ฒฉ ์ ๋ณด๋ฅผ ์์ฒญํ๋ ๋ฑ
์ฒซ ๋ฒ์งธ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ๋๊ธฐํ์ง ์๊ณ ๋ค๋ฅธ ์์
์ ์ฒ๋ฆฌํ ์ ์๋ค.
- ์๋ก ์ ๊ณตํ๋ API ๊ฐ ๋ค๋ฅด๋ค.
- ๋น๋๊ธฐ๋ฅผ ์ง์ํ๋ค๋ ์ ์ ๋์ผํ๋ค.
- ๋ฉ์๋ ์ฒด์ด๋์ ์ง์ํ๋ค๋ ์ ์์ CompletableFuture ๊ฐ ๊ฐ๋ ์ฑ์ด ๋ ์ข๋ค.
https://stackoverflow.com/questions/52303472/executorservice-vs-completablefuture
- async
- ์์ ์ ์คํํ๊ณ ์์ฒญ ์ค๋ ๋๋ ๋ค๋ฅธ ์์ ์ ์คํ
- ์คํ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ฒฝ์ฐ์ง ์์
- sync
- ์ด๋ฒคํธ๋ฅผ ์์ ์ด ์ง์ ์ฒ๋ฆฌ(ํ์ธ์ ์ฃผ์ฒด๊ฐ ์ ์ ํ๋ก์ธ์ค์ด๋ฉฐ, ๋ค ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ์ค์ค๋ก ํ์ธ)
- ๋ฉ์๋,์์ ๋ฑ์ ์คํํ๊ณ ํด๋น ๋ฉ์๋์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ด์ฌ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋ฐฉ์
- block
- ์๋ฃ๊น์ง ๋๊ธฐ(๋ฆฌํด๋๊ธฐ ์ ๊น์ง ๋ฉ์ถค)
- non-block
- ๋ฏธ์๋ฃ๋ผ๋ ์ฆ์ ๋ฆฌํด
- ๋๊ธฐ API
- ๋๊ธฐ API ์์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ค์ ๋ฉ์๋๊ฐ ๊ณ์ฐ์ ์๋ฃํ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฉ์๋๊ฐ ๋ฐํ๋๋ฉด ํธ์ถ์๋ ๋ฐํ๋ ๊ฐ์ผ๋ก ๊ณ์ ๋ค๋ฅธ ๋์์ ์ํํ๋ค.
์ด์ฒ๋ผ ํธ์ถ์๋ ํผํธ์ถ์์
์์ ์๋ฃ
๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ, ๋๊ธฐ API ๋ฅผ ์ฌ์ฉํ๋ ์ํฉ์๋ธ๋ก ํธ์ถ(blocking call)
์ด๋ผ๊ณ ํ๋ค.
- ๋๊ธฐ API ์์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ค์ ๋ฉ์๋๊ฐ ๊ณ์ฐ์ ์๋ฃํ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฉ์๋๊ฐ ๋ฐํ๋๋ฉด ํธ์ถ์๋ ๋ฐํ๋ ๊ฐ์ผ๋ก ๊ณ์ ๋ค๋ฅธ ๋์์ ์ํํ๋ค.
์ด์ฒ๋ผ ํธ์ถ์๋ ํผํธ์ถ์์
- ๋น๋๊ธฐ API
- ๋น๋๊ธฐ API ์์๋ ๋ฉ์๋๊ฐ ์ฆ์ ๋ฐํ๋๋ฉฐ ๋๋ด์ง ๋ชปํ ๋๋จธ์ง ์์
์ ํธ์ถ์ ์ค๋ ๋์ ๋๊ธฐ์ ์ผ๋ก ์คํ๋ ์ ์๋๋ก ๋ค๋ฅธ ์ค๋ ๋์ ํ ๋นํ๋ค. ์ด์ ๊ฐ์ ๋น๋๊ธฐ API ๋ฅผ ์ฌ์ฉํ๋ ์ํฉ์
๋น๋ธ๋ก ํธ์ถ(non-blocking call)
์ด๋ผ๊ณ ํ๋ค.
- ๋น๋๊ธฐ API ์์๋ ๋ฉ์๋๊ฐ ์ฆ์ ๋ฐํ๋๋ฉฐ ๋๋ด์ง ๋ชปํ ๋๋จธ์ง ์์
์ ํธ์ถ์ ์ค๋ ๋์ ๋๊ธฐ์ ์ผ๋ก ์คํ๋ ์ ์๋๋ก ๋ค๋ฅธ ์ค๋ ๋์ ํ ๋นํ๋ค. ์ด์ ๊ฐ์ ๋น๋๊ธฐ 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 ํ๋ ์์ํฌ๋ค์ ๋ฌดํ๋ฃจํ๋ฅผ ํตํด ์๋ต๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋์ง ์ง์์ ์ผ๋ก ํ์ธํ๋ค.(poll) ์ด๋ฅผ
์ด๋ฒคํธ ๋ฃจํ
๋ผ๊ณ ๋ถ๋ฅธ๋ค.- ์ฆ, ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ํตํด์ socket ์์ ์ฝ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง ๊ณ์ ํ์ธํ๋ค.
- ๋ฆฌ๋ ์ค epoll, io_uring (์๋ฐ NIO์์ ์๋์ฐ๋ select, ๋งฅ์ kqueue, ๋ฆฌ๋ ์ค๋ epoll์ ์ง์)
- ์ด๊ฒ์ด ์๋ฐ๋ค
- Modern Java In Action
- https://www.eginnovations.com/blog/java-threads/
- https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism
- https://stackoverflow.com/questions/34689709/java-threads-and-number-of-cores/34689857#34689857
- https://javacan.tistory.com/entry/134
- https://pjh3749.tistory.com/280
- https://stackoverflow.com/questions/1241429/blocking-io-vs-non-blocking-io-looking-for-good-articles
- https://alwayspr.tistory.com/44
- https://github-wiki-see.page/m/GANGNAM-JAVA/JAVA-STUDY/wiki/Blocking,Non-Blocking,-Synchronous,-Asynchronous
- https://stackify.dev/222347-executorservice-vs-completablefuture
- https://kwonnam.pe.kr/wiki/java/8/completable_future