[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] Item07 ์™„๋ฒฝ๊ณต๋žต. Executor

2023. 1. 21. 21:58ใ†JAVA/Effective JAVA

728x90
item07. ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ. 

" p39. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์“ฐ๋ ˆ๋“œ, ScheduledThreadPoolExecutor"

 

 

Executor๋ฅผ ์•Œ๊ธฐ์ „์— Thread, Runnable์ด ๋ญ”์ง€๋ถ€ํ„ฐ ์•Œ์•„์•ผ Executor๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 

๋จผ์ € Thread์™€ Runnable์ด ๋ฌด์—‡์ธ์ง€๋ถ€ํ„ฐ ์ฐพ์•„๋ดค๋‹ค. 

 

์šฐ์„  ์“ฐ๋ ˆ๋“œ๋ž€ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์˜ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„๋กœ, ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด ์‹คํ–‰ํ•˜๋ฉด 1๊ฐœ์˜ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋œ๋‹ค. 

๊ทธ๋Ÿฐ๋ฐ 1๊ฐœ์˜ ์Šค๋ ˆ๋“œ ๊ฐ€์ง€๊ณ ๋Š” ๋™์‹œ์— ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ๋™์‹œ์— ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. 

์ž๋ฐ”์—์„œ๋Š” ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด์„œ Runnable, Thread, Callable, Executor, Future, ExecutorService, Excutors... ๋“ฑ ๋ฐฉ๋ฒ•๋“ค์„ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค. 

 

 

- Thread

: Thread ํด๋ž˜์Šค๋Š” ์ž๋ฐ”์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์‹œ ๋Œ€ํ‘œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค. 

 

 

- Runnable 

:  Runnable์€ 1๊ฐœ์˜ ๋ฉ”์†Œ๋“œ ๋งŒ์„ ๊ฐ–๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค. 

static class Task implements Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread() + " world");
    }
}
        Thread thread = new Thread(new Task());
        thread.start();

        System.out.println(Thread.currentThread() + " hello");

์ด๋ ‡๊ฒŒ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ž‘์—…ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

- callable

: Runnable๊ณผ ๋น„์Šทํ•œ๋ฐ Runnable์€ ๋ฆฌํ„ด๊ฐ’์ด ์—†์ง€๋งŒ Callalbe์€ ๋ฆฌํ„ด๊ฐ’๋„ ์ค„ ์ˆ˜ ์žˆ๋‹ค. 

๋”ฐ๋ผ์„œ ๋ฆฌํ„ด๊ฐ’์„ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์ด๋ผ๋ฉด Callable์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

static class CallableTask implements Callable<String> {

    @Override
    public String call() throws Exception {
        Thread.sleep(2000L);
        return Thread.currentThread() + " world";
    }
}

 

 

- ThreadPool

๋งŒ์•ฝ ์Šค๋ ˆ๋“œ๋ฅผ 100๊ฐœ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ทธ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๋„ ๋˜๋ฉฐ, ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ์ ์ด๋‹ค. 

๋”ฐ๋ผ์„œ ์ž๋ฐ”์—์„œ๋Š” ์“ฐ๋ ˆ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ThreadPool์ด๋ž€๊ฒƒ์„ ์ œ๊ณตํ•ด ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. 

Executor ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์“ฐ๋ ˆ๋“œ ํ’€์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ExecutorService๊ฐ€ ์ž‘์—…(Runnable, Callalbe) ๋“ฑ๋ก์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ Executor๋ฅผ ์ƒ์†๋ฐ›์•„์„œ ์ž‘์—… ๋“ฑ๋ก ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‹คํ–‰์„ ์œ„ํ•œ ์ฑ…์ž„๋„ ๊ฐ–๋Š”๋‹ค. 

๋”ฐ๋ผ์„œ ์“ฐ๋ ˆ๋“œ ํ’€์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ExecutorServie์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. 

์ง์ ‘ ์“ฐ๋ ˆ๋“œ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด ๋ฒˆ๊ฑฐ๋กญ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋„์™€์ฃผ๋Š” ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋กœ Executors๋ฅผ ์ œ๊ณตํ•œ๋‹ค. 

Executors ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์“ฐ๋ ˆ๋“œ ํ’€์„ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ Thread๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

newFixedThreadPool

: ์ฃผ์–ด์ง„ ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋งŒํผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ์ˆ˜๋ฅผ ์œ ์ง€ํ•œ๋‹ค. 

ExecutorService service = Executors.newFixedThreadPool(10);

newFixedThreadPool์„ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ๋Œ€ 10๊ฐœ๋งŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ณ , ๋‚˜๋จธ์ง€ ์ž‘์—…์„ ํ•  ๋•Œ๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ๋œป์ด๋‹ค. 

๋”ฐ๋ผ์„œ ์ƒˆ๋กœ์šด ์ž‘์—…์ด ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ์Šค๋ ˆ๋“œ๋Š” 10๊ฐœ ์ด์ƒ ์ƒ์„ฑ๋˜์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€๋Š” ์žฌ์‚ฌ์šฉ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„์— ๋Œ€ํ•œ ๋ถ€๋‹ด์—†์ด ์ƒˆ๋กœ์šด ์ž‘์—…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

newCachedThreadPool

: ์ฒ˜๋ฆฌํ•  ์ž‘์—…์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๊ทธ ๋งŒํผ ์Šค๋ ˆ๋“œ๋ฅผ ์ฆ๊ฐ€ํ•˜์—ฌ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋•Œ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ์— ์ œํ•œ์„ ๋‘์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๋กœ ์ด์–ด์งˆ ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์กฐ์‹ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. 

ExecutorService service1 = Executors.newCachedThreadPool();

 

newSingleThreadExecutor 

: ์Šค๋ ˆ๋“œ๋ฅผ ๋‹จ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด๋‹ค. (๋น„ํšจ์œจ์ )  

ExecutorService service2 = Executors.newSingleThreadExecutor();

newScheduledThreadPool

: ํŠน์ • ์‹œ๊ฐ„ ์ดํ›„์— ์‹คํ–‰๋˜๊ฑฐ๋‚˜ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ž‘์—…์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. 

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);

 

 

๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ cpu์— ๋ฏผ๊ฐํ•˜๋‹ค๋ฉด 

int numberOfCpu = Runtime.getRuntime().availableProcessors(); 

์ด๋Ÿฐ์‹์œผ๋กœ cpu์˜ ๊ฐœ์ˆ˜์— ๋งž์ถฐ์„œ ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋ฅผ ํ• ๋‹นํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 

 

 

 

for (int i = 0; i < 100; i++) {
    service.submit(new Task());
}

์ž‘์—…์€ Callable, Runnable ์˜ ํ˜•ํƒœ๋กœ ์ถ”๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , submit ํ•จ์ˆ˜๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค. 

 

Future<String> submit = service.submit(new CallableTask());
System.out.println(submit.get());

๊ทธ๋ฆฌ๊ณ  ์ด๋•Œ Callable์˜ ๋ฆฌํ„ด ๊ฐ’์€ Future๋กœ ๋ฐ›๊ฒŒ ๋˜๊ณ , get์„ ํ†ตํ•ด์„œ ๊ฒฐ๊ณผ ๊ฐ’์„ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90