ν‹°μŠ€ν† λ¦¬ λ·°

 ExecutorService 

πŸ”₯ μžλ°”μ˜ μŠ€λ ˆλ“œλ₯Ό νŽΈν•˜κ²Œ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ 라이브러리둜 μŠ€λ ˆλ“œ 풀및 μŠ€λ ˆλ“œ 생성 ν˜Ήμ€ κ·Έ μž‘μ—…μ„ κ°€λŠ₯ν•˜κ²Œ ν•œλ‹€.

   newFixedThreadPool(int) 

πŸ–ŒοΈ ThreadPool (ThreadPoolExecutor) 생성을 μœ„ν•œ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ€‘ ν•˜λ‚˜λ‘œ

     μΈμž 개수만큼 κ³ μ •λœ ThreadPool 을 λ§Œλ“ λ‹€.

 

// μŠ€λ ˆλ“œκ°€ 20개둜 κ³ μ •λ˜λŠ” Thread Pool μƒμ„±ν•œλ‹€.
ExecutorService es = Executors.newFixedThreadPool(20);

 newCachedThreadPool 

πŸ–ŒοΈ ThreadPool (ThreadPoolExecutor) 생성을 μœ„ν•œ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ€‘ ν•˜λ‚˜λ‘œ ν•„μš”ν•  λ•Œ, ν•„μš”ν•œ 만큼 ThreadPool 을 λ§Œλ“ λ‹€. 이미 μƒμ„±λœ μ“°λ ˆλ“œλ₯Ό μž¬μ‚¬μš© ν•΄ μ„±λŠ₯μƒμ˜ 이점이 μžˆμ„ 수 μžˆλ‹€.
// Thread Pool 생성
ExecutorService es = Executors.newCachedThreadPool();

 

  newSingleThreadExecutor() 

πŸ–ŒοΈ μ“°λ ˆλ“œ ν•œ 개인 ExecutorServiceλ₯Ό μƒμ„±ν•˜λŠ” 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ‹€. μ‹±κΈ€ μ“°λ ˆλ“œ μž‘μ—…μ„ μ²˜λ¦¬ν•  λ•Œ μ‚¬μš©ν•œλ‹€.

 

// μ‹±κΈ€ μ“°λ ˆλ“œ ExecutorService λ₯Ό μƒμ„±ν•œλ‹€.
ExecutorService es = Executors.newSingleThreadExecutor();

 execute(Runnable run) 

πŸ‘Ÿ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό 톡해 Runnable 을 μ‹€ν–‰ν•œλ‹€.
  es.execute(() -> {
      try {
        Thread.sleep(2000);
      } catch (InterruptedException e) {}
      log.info("Async");
    });
    log.info("Exit");
  }

κ²°κ³Ό

07:49:58.256 [main] INFO asynchronous.toby.FutureEx - Exit
07:50:00.260 [pool-1-thread-1] INFO asynchronous.toby.FutureEx - Async

 submit(Callable task) 

πŸ‘Ÿ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό 톡해 Callable 을 μ‹€ν–‰ν•˜μ—¬ κ·Έ κ²°κ³Ό 값을 λ°˜ν™˜ν•œλ‹€. 이 λ•Œ λ°˜ν™˜ν•˜λŠ” 값을 Future λ₯Ό 톡해 받을 수 μžˆλ‹€.
Future<String> future = es.submit(() -> {
      Thread.sleep(2000);
      log.info("Async");
      return "Hello";
});

 Future 

πŸ”₯ λ―Έλž˜μ— 싀행될 비동기 μž‘μ—…μ„ ν†΅ν•œ 결과에 λŒ€ν•œ ν•Έλ“€λŸ¬(Hanlder)

  get() 

πŸ‘Ÿ Callable 의 μž‘μ—… κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œ. ν•΄λ‹Ή λ©”μ„œλ“œ μ‹€ν–‰ μ‹œ μŠ€λ ˆλ“œ μ‹€ν–‰μ˜ κ²°κ³Ό 값이 λ°˜ν™˜ ν•  λ•Œ κΉŒμ§€ λΈ”λ‘œν‚Ή(Blocking) μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€.

πŸ€” λ§€κ°œλ³€μˆ˜λ₯Ό 톡해 Timeout 을 μ§€μ •ν•˜λŠ” 방법도 μžˆλ‹€.

 

// μž‘μ—…(Task) μ‹œμž‘ 
Future<String> future = es.submit(() -> { 
      Thread.sleep(2000);
      log.info("Async");
      return "Hello";
  });

//Blocking : κ²°κ³Όλ₯Ό λ°›κΈ° μœ„ν•΄ ν•΄λ‹Ή μŠ€λ ˆλ“œμ—μ„œ κ²°κ³Ό 값을 λ°›κΈ° μ „ κΉŒμ§€ 블둝킹을 ν•˜κ³  μžˆλ‹€.
String hello = future.get(); 

System.out.println(hello);
log.info("Exit");

 

 

κ²°κ³Ό

07:45:20.340 [pool-1-thread-1] INFO asynchronous.toby.FutureEx - Async
Hello
07:45:20.346 [main] INFO asynchronous.toby.FutureEx - Exit

  isDone() 

πŸ‘Ÿ Callable 의 μž‘μ—…μ˜ ν˜„μž¬ μƒνƒœλ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œμ΄λ‹€.
    μž‘μ—…μ΄ μ™„λ£Œ λ˜μ—ˆλ‹€λ©΄ True λ₯Ό 아직 μž‘μ—…μ΄ μ™„λ£Œλ˜μ§€ μ•Šμ€ μƒνƒœλΌλ©΄ False λ₯Ό λ°˜ν™˜ν•œλ‹€.
    이 λ©”μ„œλ“œλŠ” λ…Ό 블둝킹(Non-Blocking) 으둜 μž‘λ™ν•œλ‹€.

 

Future<String> future = es.submit(() -> {
      Thread.sleep(2000);
      log.info("Async");
      return "Hello";
});

System.out.println(future.isDone());
Thread.sleep(2100);
log.info("Exit");
System.out.println(future.get());

 

κ²°κ³Ό

08:01:03.626 [pool-1-thread-1] INFO asynchronous.toby.FutureEx - Async
true
08:01:07.736 [main] INFO asynchronous.toby.FutureEx - Exit
Hello

  FutureTask 

πŸ”₯ Future 와 Callable(비동기 μž‘μ—…) 을 ν†΅ν•©ν•œ κΈ°λ³Έ κ΅¬ν˜„μ²΄

  done() 

πŸ‘Ÿ FutureTask μ˜ execute(비동기 μž‘μ—…)이 끝날 λ•Œ ν˜ΈμΆœλ˜λŠ” Protected λ©”μ„œλ“œλ‘œ κ²°κ³Όλ₯Ό κ°€λ‘œμ±„λŠ” ν›„ν‚Ή(Hooking) 이 κ°€λŠ₯ν•˜λ‹€.
FutureTask<String> future = new FutureTask<>(() -> {
      Thread.sleep(2000);
      log.info("Async");
      return "Hello";
     }) {
      // 비동기 μž‘μ—…μ΄ 끝날 λ•Œ ν˜ΈμΆœλ˜λŠ” λ©”μ„œλ“œλ‘œ 후킹이 κ°€λŠ₯ν•˜λ‹€.
      @Override
      protected void done() {
        try {
          System.out.println(get());
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        }
        };

    es.execute(future);
    es.shutdown();

 

κ²°κ³Ό
08:11:31.097 [pool-1-thread-1] INFO asynchronous.toby.FutureEx - Async
Hello

 

μ°Έμ‘°

λŒ“κΈ€