๋‹ค๋ฅธ ์œ ํ˜•์˜ ์Šค๋ ˆ๋“œ ํ’€์€ "์บ์‹œ"์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์Šค๋ ˆ๋“œ ํ’€์€ ๊ณ ์ • ์Šค๋ ˆ๋“œ ํ’€๋งŒํผ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์Šค๋ ˆ๋“œ ํ’€์€ ์Šค๋ ˆ๋“œ๋ฅผ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ œํ•œ๋œ ์‹œ๊ฐ„ ๋™์•ˆ ํ™œ์„ฑ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜์—ฌ ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์Šค๋ ˆ๋“œ ํ’€์€ ํ•ฉ๋ฆฌ์ ์ธ ์–‘์˜ ๊ฐ€๋ฒผ์šด ์ž‘์—…์ด ์žˆ์„ ๋•Œ ๊ฐ€์žฅ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

"ํ•ฉ๋ฆฌ์ ์ธ ๊ธˆ์•ก"์˜ ์˜๋ฏธ๋Š” ๋‹ค์†Œ ๊ด‘๋ฒ”์œ„ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ํ’€์ด ๋ชจ๋“  ์ž‘์—… ์ˆ˜์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค๋Š” ์ ์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐฑ๋งŒ ๊ฐœ์˜ ์ž‘์—…์„ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—…์— ์•„์ฃผ ์ ์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋”๋ผ๋„ ์—ฌ์ „ํžˆ ๋ถˆํ•ฉ๋ฆฌํ•œ ์–‘์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด I/O ์ž‘์—…๊ณผ ๊ฐ™์ด ์‹คํ–‰ ์‹œ๊ฐ„์„ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์—๋„ ์ด๋Ÿฌํ•œ ํ’€์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ ThreadPoolExecutor ์ƒ์„ฑ์ž๋Š” ๋‹ค์Œ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.


public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, 
      new SynchronousQueue<Runnable>());
}

๋‹ค์Œ ๊ฐ’์€ ์ƒ์„ฑ์ž์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

๋ชจ์ˆ˜ ๊ฐ’
corePoolSize ( ์‹คํ–‰์ž ์„œ๋น„์Šค๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์ค€๋น„(์‹œ์ž‘)๋  ์Šค๋ ˆ๋“œ ์ˆ˜ ) 0
maximumPoolSize ( ์‹คํ–‰๊ธฐ ์„œ๋น„์Šค๊ฐ€ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์Šค๋ ˆ๋“œ ์ˆ˜ ) ์ •์ˆ˜.MAX_VALUE
keepAliveTime (์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ corePoolSize ๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ ํ•ด์ œ๋œ ์Šค๋ ˆ๋“œ๊ฐ€ ์†Œ๋ฉธ๋˜๊ธฐ ์ „์— ๊ณ„์† ์œ ์ง€๋˜๋Š” ์‹œ๊ฐ„ ) 60L
๋‹จ์œ„ (์‹œ๊ฐ„ ๋‹จ์œ„) TimeUnit.SECONDS
workQueue (๋Œ€๊ธฐ์—ด ๊ตฌํ˜„) ์ƒˆ๋กœ์šด SynchronousQueue<์‹คํ–‰ ๊ฐ€๋Šฅ>()

๊ทธ๋ฆฌ๊ณ  ์ •ํ™•ํžˆ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์šฐ๋ฆฌ ์ž์‹ ์˜ ThreadFactory ๊ตฌํ˜„์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SynchronousQueue์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

์ƒˆ ์ž‘์—…์ด ๋Œ€๊ธฐ์—ด์— ๋“ค์–ด์˜ฌ ๋•Œ ํ’€์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ™œ์„ฑ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์ž‘์—…์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ด๋ฉด ์ƒˆ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์บ์‹œ๋œ ํ’€์€ 0๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋กœ ์‹œ์ž‘ํ•˜์—ฌ ์ž ์žฌ์ ์œผ๋กœ Integer.MAX_VALUE ์Šค๋ ˆ๋“œ๋กœ ํ™•์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹œ๋œ ์Šค๋ ˆ๋“œ ํ’€์˜ ํฌ๊ธฐ๋Š” ์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค์— ์˜ํ•ด์„œ๋งŒ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ ˆ์•ฝํ•˜๊ธฐ ์œ„ํ•ด ์บ์‹œ๋œ ์Šค๋ ˆ๋“œ ํ’€์€ 1๋ถ„ ๋™์•ˆ ์œ ํœด ์ƒํƒœ์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ด…์‹œ๋‹ค. ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ๋ชจ๋ธ๋งํ•˜๋Š” ํƒœ์Šคํฌ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.


public class Task implements Runnable {
   int taskNumber;

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

   @Override
   public void run() {
       System.out.println("Processed user request #" + taskNumber + " on thread " + Thread.currentThread().getName());
   }
}
    

๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ ์—์„œ newCachedThreadPool์„ ์ƒ์„ฑํ•œ ๋‹ค์Œ ์‹คํ–‰์„ ์œ„ํ•ด 3๊ฐœ์˜ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์„œ๋น„์Šค ์ƒํƒœ๋ฅผ ์ธ์‡„ํ•ฉ๋‹ˆ๋‹ค (1) .

๋‹ค์Œ์œผ๋กœ 30์ดˆ ๋™์•ˆ ์ผ์‹œ ์ค‘์ง€ํ•˜๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ณ  ์ƒํƒœ (2) ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค .

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ 70์ดˆ ๋™์•ˆ ์ผ์‹œ ์ค‘์ง€ํ•˜๊ณ  ์ƒํƒœ (3)๋ฅผ ์ธ์‡„ํ•œ ๋‹ค์Œ ๋‹ค์‹œ 3๊ฐœ์˜ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ƒํƒœ (4) ๋ฅผ ๋‹ค์‹œ ์ธ์‡„ํ•ฉ๋‹ˆ๋‹ค .

์ž‘์—…์„ ์ถ”๊ฐ€ํ•œ ์งํ›„์— ์ƒํƒœ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์œ„์น˜์—์„œ ์ตœ์‹  ์ถœ๋ ฅ์„ ์œ„ํ•ด ๋จผ์ € 1์ดˆ ์ ˆ์ „์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.


ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 3; i++) {
            executorService.submit(new Task(i));
        }
 
        TimeUnit.SECONDS.sleep(1);
            System.out.println(executorService);	//(1)
 
        TimeUnit.SECONDS.sleep(30);
 
        executorService.submit(new Task(3));
        TimeUnit.SECONDS.sleep(1);
            System.out.println(executorService);	//(2)
 
        TimeUnit.SECONDS.sleep(70);
 
            System.out.println(executorService);	//(3)
 
        for (int i = 4; i < 7; i++) {
            executorService.submit(new Task(i));
        }
 
        TimeUnit.SECONDS.sleep(1);
            System.out.println(executorService);	//(4)
        executorService.shutdown();

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

pool-1-thread-1 ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #0
pool-1-thread-2 ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ
#1 pool-1-thread-3 ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #2
(1) java.util.concurrent .ThreadPoolExecutor@f6f4d33[์‹คํ–‰ ์ค‘, ํ’€ ํฌ๊ธฐ = 3, ํ™œ์„ฑ ์Šค๋ ˆ๋“œ = 0, ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… = 0, ์™„๋ฃŒ๋œ ์ž‘์—… = 3]
pool-1-thread-2 ์Šค๋ ˆ๋“œ
(2) java.util.concurrent์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #3. ThreadPoolExecutor@f6f4d33[์‹คํ–‰ ์ค‘, ํ’€ ํฌ๊ธฐ = 3, ํ™œ์„ฑ ์Šค๋ ˆ๋“œ = 0, ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… = 0, ์™„๋ฃŒ๋œ ์ž‘์—… = 4] (3)
java.util.concurrent.ThreadPoolExecutor@f6f4d33[์‹คํ–‰ ์ค‘, ํ’€ ํฌ๊ธฐ = 0, ํ™œ์„ฑ ์Šค๋ ˆ๋“œ = 0 , ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… = 0, ์™„๋ฃŒ๋œ ์ž‘์—… = 4]
pool-1-thread-4 ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #4
pool-1-thread-5 ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #5
pool-1-thread-4 ์Šค๋ ˆ๋“œ
(4)์—์„œ ์ฒ˜๋ฆฌ๋œ ์‚ฌ์šฉ์ž ์š”์ฒญ #6 java.util.concurrent.ThreadPoolExecutor@f6f4d33[์‹คํ–‰ ์ค‘, ํ’€ ํฌ๊ธฐ = 2, ํ™œ์„ฑ ์Šค๋ ˆ๋“œ = 0, ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… = 0, ์™„๋ฃŒ๋œ ์ž‘์—… = 7]

๊ฐ ๋‹จ๊ณ„๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹จ๊ณ„ ์„ค๋ช…
1(์ž‘์—… 3๊ฐœ ์™„๋ฃŒ ํ›„) ์šฐ๋ฆฌ๋Š” 3๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ–ˆ๊ณ  ์ด 3๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—์„œ 3๊ฐœ์˜ ์ž‘์—…์ด ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ƒํƒœ๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด 3๊ฐ€์ง€ ์ž‘์—…์ด ๋ชจ๋‘ ์™„๋ฃŒ๋˜๊ณ  ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ค€๋น„๊ฐ€ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
2(30์ดˆ ์ผ์‹œ ์ค‘์ง€ ํ›„ ๋‹ค๋ฅธ ์ž‘์—… ์‹คํ–‰) 30์ดˆ ๋™์•ˆ ํ™œ๋™์ด ์—†์œผ๋ฉด ์Šค๋ ˆ๋“œ๋Š” ์—ฌ์ „ํžˆ ํ™œ์„ฑ ์ƒํƒœ์ด๋ฉฐ ์ž‘์—…์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
๋‚˜๋จธ์ง€ ๋ผ์ด๋ธŒ ์Šค๋ ˆ๋“œ ํ’€์—์„œ ๊ฐ€์ ธ์˜จ ์Šค๋ ˆ๋“œ์—์„œ ๋‹ค๋ฅธ ์ž‘์—…์ด ์ถ”๊ฐ€๋˜๊ณ  ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
ํ’€์— ์ถ”๊ฐ€๋œ ์ƒˆ ์Šค๋ ˆ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
3(70์ดˆ ์ผ์‹œ ์ค‘์ง€ ํ›„) ์Šค๋ ˆ๋“œ๊ฐ€ ํ’€์—์„œ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ž‘์—…์„ ์ˆ˜๋ฝํ•  ์ค€๋น„๊ฐ€ ๋œ ์Šค๋ ˆ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
4(3๊ฐœ์˜ ์ž‘์—…์„ ๋” ์‹คํ–‰ํ•œ ํ›„) ๋” ๋งŽ์€ ์ž‘์—…์ด ์ˆ˜์‹ ๋œ ํ›„ ์ƒˆ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋งŒ 3๊ฐœ์˜ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๋‹ค๋ฅธ ์œ ํ˜•์˜ ์‹คํ–‰์ž ์„œ๋น„์Šค ๋…ผ๋ฆฌ์— ์ต์ˆ™ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

Executors ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค ์˜ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ newCachedThreadPool ๋ฉ”์„œ๋“œ์—๋Š” ThreadFactory ๊ฐœ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ์˜ค๋ฒ„๋กœ๋“œ๋œ ๋ฒ„์ „๋„ ์žˆ์Šต๋‹ˆ๋‹ค .