1 ์Šค๋ ˆ๋“œ์— ExecutorService๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

Executors.newSingleThreadExecutor ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํ’€์ด ์žˆ๋Š” ExecutorService๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ’€์˜ ๋…ผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ž‘์—…๋งŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ์‹คํ–‰์„ ์œ„ํ•ด N๊ฐœ์˜ ์ž‘์—…์„ ์ œ์ถœํ•˜๋ฉด ๋ชจ๋“  N๊ฐœ์˜ ์ž‘์—…์ด ๋‹จ์ผ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์ฐจ๋ก€๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ์Šค๋ ˆ๋“œ๊ฐ€ ์ค‘๋‹จ๋˜๋ฉด ๋‚˜๋จธ์ง€ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์— ๋‹ค์Œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์„ ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค.

30์ดˆ ์ด๋‚ด์— ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜์ง€๋งŒ ๋‹จ์œ„ ์‹œ๊ฐ„๋‹น ํ•˜๋‚˜์˜ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—… ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

class Task implements Runnable {
   private final int taskNumber;

   public Task(int taskNumber) {
       this.taskNumber = taskNumber;
   }

   @Override
   public void run() {
       try {
           Thread.sleep(1000);
       } catch (InterruptedException ignored) {
       }
       System.out.printf("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
   }
}

์ด ํด๋ž˜์Šค๋Š” ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์ž‘์„ ๋ชจ๋ธ๋งํ•˜๊ณ  ํ•ด๋‹น ๋ฒˆํ˜ธ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ, ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์Šค๋ ˆ๋“œ 1๊ฐœ์— ๋Œ€ํ•œ ExecutorService๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค . ์ž‘์—… ์กฐ๊ฑด์ด "30์ดˆ ์ด๋‚ด"๋กœ ๊ทœ์ •๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ 30์ดˆ ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ ExecutorService๋ฅผ ๊ฐ•์ œ๋กœ ์ค‘์ง€ ํ•ฉ๋‹ˆ๋‹ค .

public static void main(String[] args) throws InterruptedException {
   ExecutorService executorService = Executors.newSingleThreadExecutor();

   for (int i = 0; i < 1_000; i++) {
       executorService.execute(new Task(i));
   }
   executorService.awaitTermination(30, TimeUnit.SECONDS);
   executorService.shutdownNow();
}

ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•˜๋ฉด ์ฝ˜์†”์— ์š”์ฒญ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #0
์Šค๋ ˆ๋“œ id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #1 ์Šค๋ ˆ๋“œ
id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #2
โ€ฆ
์Šค๋ ˆ๋“œ id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #29

30์ดˆ ๋™์•ˆ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ ํ›„ executorService๋Š” ํ˜„์žฌ ์ž‘์—…(์‹คํ–‰ ์ค‘์ธ ์ž‘์—…)์„ ์ค‘์ง€ํ•˜๊ณ  ๋ณด๋ฅ˜ ์ค‘์ธ ๋ชจ๋“  ์ž‘์—…์„ ์ทจ์†Œํ•˜๋Š” shutdownNow() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค . ๊ทธ ํ›„ ํ”„๋กœ๊ทธ๋žจ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ชจ๋“  ๊ฒƒ์ด ํ•ญ์ƒ ์™„๋ฒฝํ•œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ํ’€์˜ ์œ ์ผํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์„ ํƒํ•œ ์ž‘์—… ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ž˜๋ชป ์ž‘๋™ํ•˜๊ณ  ์‹ฌ์ง€์–ด ์Šค๋ ˆ๋“œ๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์ƒํ™ฉ์„ ์‰ฝ๊ฒŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์„ ์‹œ๋ฎฌ๋ ˆ์ดํŠธํ•˜์—ฌ ์ด ๊ฒฝ์šฐ executorService๊ฐ€ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋กœ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .

์ด๋ฅผ ์œ„ํ•ด ์ž‘์—… ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ์•ˆ์ „ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” Thread.currentThread().stop() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘ ํ•˜๋‚˜๊ฐ€ ์Šค๋ ˆ๋“œ๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์ƒํ™ฉ์„ ์‹œ๋ฎฌ๋ ˆ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Task ํด๋ž˜์Šค ์—์„œ run ๋ฉ”์„œ๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค .

@Override
public void run() {
   try {
       Thread.sleep(1000);
   } catch (InterruptedException ignored) {
   }

   if (taskNumber == 5) {
       Thread.currentThread().stop();
   }

   System.out.printf("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
}

์ž‘์—… #5๋ฅผ ์ค‘๋‹จํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž‘์—… #5์˜ ๋์—์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ค‘๋‹จ๋œ ์ถœ๋ ฅ์ด ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ๋ด…์‹œ๋‹ค.

์Šค๋ ˆ๋“œ id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #0 ์Šค๋ ˆ๋“œ
id=16์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #1 ์Šค๋ ˆ๋“œ id=16์—์„œ
์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #2 ์Šค๋ ˆ๋“œ id=16
์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #3 ์Šค๋ ˆ๋“œ id=16
์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #4 ์Šค๋ ˆ๋“œ id=16์—์„œ
์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #6 thread id=17
thread id=17์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #7
โ€ฆ
thread id=17์—์„œ ์ฒ˜๋ฆฌ๋œ ์š”์ฒญ #29

์ž‘์—… 5์˜ ๋์—์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ค‘๋‹จ๋œ ํ›„ ์ž‘์—…์€ ์ด์ „์— ์‹๋ณ„์ž๊ฐ€ 16์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜์—ˆ์ง€๋งŒ ์‹๋ณ„์ž๊ฐ€ 17์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ ์Šค๋ ˆ๋“œ, ์ด๊ฒƒ์€ ๋‹จ์ง€ ํ•œ ๊ฐ€์ง€๋ฅผ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. executorService๋Š” ์ค‘์ง€๋œ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒˆ ์Šค๋ ˆ๋“œ๋กœ ๊ต์ฒดํ•˜๊ณ  ์ž‘์—…์„ ๊ณ„์† ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ž‘์—…์„ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ด์ „ ์ž‘์—…์˜ ์™„๋ฃŒ์™€ ๊ด€๊ณ„์—†์ด ๋Œ€๊ธฐ์—ด์—์„œ ์ž‘์—…์„ ๊ณ„์† ์ฒ˜๋ฆฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ’€๊ณผ ํ•จ๊ป˜ newSingleThreadExecutor๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: ์Šค๋ ˆ๋“œ๋ฅผ ์ฃฝ์ž…๋‹ˆ๋‹ค).

์Šค๋ ˆ๋“œํŒฉํ† ๋ฆฌ

์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ์žฌ์ƒ์„ฑ์— ๋Œ€ํ•ด ๋งํ•  ๋•Œ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.์Šค๋ ˆ๋“œํŒฉํ† ๋ฆฌ.

ใ…์Šค๋ ˆ๋“œํŒฉํ† ๋ฆฌ์š”์ฒญ ์‹œ ์ƒˆ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

์ž์ฒด ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ํŒฉํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ธ์Šคํ„ด์Šค๋ฅผ Executors.newSingleThreadExecutor(ThreadFactory threadFactory) ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "MyThread");
            }
        });
์ƒˆ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๊ณ  ์Šค๋ ˆ๋“œ ์ด๋ฆ„์„ ์ƒ์„ฑ์ž์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "MyThread");
                thread.setPriority(Thread.MAX_PRIORITY);
                return thread;
            }
        });
์ƒ์„ฑ๋œ ์Šค๋ ˆ๋“œ์˜ ์ด๋ฆ„๊ณผ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ 2๊ฐœ์˜ ์˜ค๋ฒ„๋กœ๋“œ๋œ Executors.newSingleThreadExecutor ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . ํ•˜๋‚˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ThreadFactory ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ThreadFactory ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์š”์— ๋”ฐ๋ผ ์ƒ์„ฑ๋œ ์Šค๋ ˆ๋“œ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: ์šฐ์„  ์ˆœ์œ„ ์„ค์ •, ์Šค๋ ˆ๋“œ ํ•˜์œ„ ํด๋ž˜์Šค ์‚ฌ์šฉ, ์Šค๋ ˆ๋“œ์— UncaughtExceptionHandler ์ถ”๊ฐ€ ๋“ฑ).