๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.


public static void main(String[] args) throws Exception {
	// Create an ExecutorService with a fixed number of threads: three
	ExecutorService service = Executors.newFixedThreadPool(3);
 
	// Pass a simple Runnable task to the ExecutorService
	service.submit(() -> System.out.println("done"));
}

ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ฉด ๊ธฐ๋Œ€ํ•˜๋Š” ์ฝ˜์†” ์ถœ๋ ฅ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์™„๋ฃŒ

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ IntelliJ IDEA์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ถœ๋ ฅ์ด ๋’ค๋”ฐ๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ข…๋ฃŒ ์ฝ”๋“œ 0์œผ๋กœ ํ”„๋กœ์„ธ์Šค ์™„๋ฃŒ

์šฐ๋ฆฌ๋Š” ๋ณดํ†ต ํ”„๋กœ๊ทธ๋žจ์ด ๋๋‚  ๋•Œ ๊ทธ๊ฒƒ์„ ๋ด…๋‹ˆ๋‹ค.

์™œ ๊ทธ๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ?

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

ExecutorService์—์„œ ์ค‘์ง€

๋”ฐ๋ผ์„œ ExecutorService ๋ฅผ "์ข…๋ฃŒ"(๋˜๋Š” ์ค‘์ง€)ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. void shutdown() โ€” ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ํ›„ ExecutorService๋Š” ์ƒˆ ์ž‘์—… ์ˆ˜๋ฝ์„ ์ค‘์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์— ExecutorService ์— ์ œ์ถœ๋œ ๋ชจ๋“  ์ž‘์—…์€ ๊ณ„์† ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

    
    public static void main(String[] args) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(3);
        	service.submit(() -> System.out.println("task 1"));
        	service.submit(() -> System.out.println("task 2"));
        	service.shutdown();
        	// A RejectedExecutionException will occur here
        	service.submit(() -> System.out.println("task 3"));
    }
    
  2. List<Runnable> shutdownNow() โ€” ์ด ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ์ž‘์—…์„ ์ค‘์ง€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ์ž์‹ ์˜ ์ฐจ๋ก€๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ์ž‘์—…์€ ํ๊ธฐ๋˜๊ณ  Runnables ๋ชฉ๋ก์œผ๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค .

    
    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List.of(1, 2, 3, 4, 5, 6, 7, 8).forEach(i -> service.submit(() -> System.out.println(i)));
        List<Runnable> runnables = service.shutdownNow();
        runnables.forEach(System.out::println);
    }
    

์‚ฐ์ถœ:

1
2
4
3
java.util.concurrent.FutureTask@1e80bfe8[์™„๋ฃŒ๋˜์ง€ ์•Š์Œ, ์ž‘์—… = java.util.concurrent.Executors$RunnableAdapter@4edde6e5[ํฌ์žฅ๋œ ์ž‘์—… = Test$$Lambda$16/0x0000000800b95040@70177ecd]]
java.util.concurrent .FutureTask@cc34f4d[์™„๋ฃŒ๋˜์ง€ ์•Š์Œ, ์ž‘์—… = java.util.concurrent.Executors$RunnableAdapter@66a29884[ํฌ์žฅ๋œ ์ž‘์—… = Test$$Lambda$16/0x0000000800b95040@4769b07b]]
java.util.concurrent.FutureTask@6f539caf[์™„๋ฃŒ๋˜์ง€ ์•Š์Œ, ์ž‘์—… = java.util.concurrent.Executors$RunnableAdapter@17a7cec2[Wrapped task = Test$$Lambda$16/0x0000000800b95040@65b3120a]]
5

ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ ์ฝ”๋“œ 0์œผ๋กœ ์™„๋ฃŒ๋จ

์ถœ๋ ฅ์€ ์‹คํ–‰๋งˆ๋‹ค ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ถœ๋ ฅ์—๋Š” ๋‘ ์ข…๋ฅ˜์˜ ๋ผ์ธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ˆซ์ž๋Š” ExecutorService ๊ฐ€ ํ•ด๋‹น ์ž‘์—…์„ ์ฒ˜๋ฆฌํ–ˆ์Œ์„ ์˜๋ฏธํ•˜๋ฉฐ ์ž‘์—…์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•œ ๋ชฉ๋ก์˜ ๋ฒˆํ˜ธ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

  • FutureTask ๊ฐ์ฒด ์—์„œ toString() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค . ์ด๋Ÿฌํ•œ ๊ฐœ์ฒด๋Š” ExecutorService ์— ์ œ์ถœ๋˜์—ˆ์ง€๋งŒ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์ž‘์—…์ž…๋‹ˆ๋‹ค .

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

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•

ExecutorService์—๋Š” ์ค‘์ง€์™€ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. boolean awaitTermination(long timeout, TimeUnit unit) โ€” ์ด ๋ฉ”์„œ๋“œ๋Š” ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ์ด๋ฒคํŠธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ฆ‰์‹œ ์ฐจ๋‹จ์ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

    • shutdown() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ํ›„ ๋ชจ๋“  ํ™œ์„ฑ ์ž‘์—…๊ณผ ์˜ˆ์•ฝ๋œ ์ž‘์—…์ด ๋ชจ๋‘ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    • ๋ฉ”์„œ๋“œ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ์˜ํ•ด ๊ฒฐ์ •๋œ ์‹œ๊ฐ„ ์ œํ•œ์ด ๊ฒฝ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.
    • awaitTermination() ๋ฉ”์„œ๋“œ ๋ฅผ ํ˜ธ์ถœํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

    ์ด ๋ฉ”์„œ๋“œ๋Š” ์ œํ•œ ์‹œ๊ฐ„์ด ๊ฒฝ๊ณผํ•˜๊ธฐ ์ „์— ExecutorService๊ฐ€ ์ค‘์ง€๋œ ๊ฒฝ์šฐ true๋ฅผ ๋ฐ˜ํ™˜ ํ•˜๊ณ  ์ œํ•œ ์‹œ๊ฐ„์ด ์ด๋ฏธ ๊ฒฝ๊ณผํ•œ ๊ฒฝ์šฐ false๋ฅผ ๋ฐ˜ํ™˜ ํ•ฉ๋‹ˆ๋‹ค.

    
    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("task 1"));
    	service.submit(() -> System.out.println("task 2"));
    	service.submit(() -> System.out.println("task 3"));
    	service.shutdown();
    	System.out.println(service.awaitTermination(1, TimeUnit.MICROSECONDS));
    }
    
  2. boolean isShutdown() โ€” ExecutorService ์—์„œ shutdown() ๋˜๋Š” shutdownNow() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ ๊ฒฝ์šฐ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค .

    
    public static void main(String[] args) throws Exception {
    	ExecutorService service = Executors.newFixedThreadPool(2);
    	service.submit(() -> System.out.println("task 1"));
    	service.submit(() -> System.out.println("task 2"));
    	service.submit(() -> System.out.println("task 3"));
    	System.out.println(service.isShutdown());
    	service.shutdown();
    	System.out.println(service.isShutdown());
    }
    
  3. boolean isTerminated() โ€” ExecutorService ์—์„œ shutdown () ๋˜๋Š” shutdownNow() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    
    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List.of(1, 2, 3, 4, 5, 6, 7, 8).forEach(i -> service.submit(() -> System.out.println(i)));
        service.shutdownNow();
        System.out.println(service.isTerminated());
    }
    

๋‹ค์Œ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ:


public static void main(String[] args) throws Exception {
   ExecutorService service = Executors.newFixedThreadPool(16);
   Callable<String> task = () -> {
       Thread.sleep(1);
       return "Done";
   };
 
   // Add 10,000 tasks to the queue
   List<Future<String>> futures = IntStream.range(0, 10_000)
           .mapToObj(i -> service.submit(task))
           .collect(Collectors.toList());
   System.out.printf("%d tasks were submitted for execution.%n", futures.size());
 
   // Attempt to shut down
   service.shutdown();
   // Wait 100 milliseconds to finish the work
   if (service.awaitTermination(100, TimeUnit.MILLISECONDS)) {
       System.out.println("All tasks completed!");
   } else {
       // Stop forcibly
       List<Runnable> notExecuted = service.shutdownNow();
       System.out.printf("%d tasks were not started.%n", notExecuted.size());
   }
 
   System.out.printf("Total tasks completed: %d.%n", futures.stream().filter(Future::isDone).count());
}

์ถœ๋ ฅ(์‹คํ–‰๋งˆ๋‹ค ๋‹ค๋ฆ„):

์‹คํ–‰์„ ์œ„ํ•ด 10,000๊ฐœ์˜ ์ž‘์—…์ด ์ œ์ถœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
9170 ์ž‘์—…์ด ์‹œ์ž‘๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
์™„๋ฃŒ๋œ ์ด ์ž‘์—…: 830๊ฐœ ์ž‘์—….

์ข…๋ฃŒ ์ฝ”๋“œ 0์œผ๋กœ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.