ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CompletableFuture (2) - Excutors
    프로그래밍/Java 2022. 5. 6. 01:58
    • 쓰레드를 만들고 관리하는 작업을 기존 Thread 를 생성하여 Runnable 를 구현하는 방식보다 보다 고수준의 API 에게 위임. 
      • (내부적으로 Runnable 방식을 쓰는것은 맞다.)
    • Excutors 가 쓰레드를 만들고, 우린 Runnable 만 제공해주면 된다.
      • (Runnable 안에 우리가 해야할 일만 정의해주면 됨)
    • Excutors 를 만들고, 필요없으면 종료 시키는 작업은 Excutors 가 직접 해준다.

     

     

     

    다시 위 내용을 정리해보자.


    고수준 (High-Level) Concurrency 프로그래밍 

    • 쓰레드를 만들고 관리하는 작업을 애플리케이션에서 분리
    • 그런 기능을 Executors 에게 위임

     

    Executors 가 하는 일

    • 쓰레드 만들기 : 애플리케이션이 사용할 쓰레드 풀을 만들어 관리한다.
    • 쓰레드 관리 : 쓰레드 생명 주기를 관리한다.
    • 작업 처리 및 실행 : 쓰레드로 실행할 작업을 제공할 수 있는 API 를 제공한다. 

     

    주요 인터페이스

    • Executor: execute(Runnable)
    • ExecutorService: Executor 상속 받은 인터페이스로, Callable도 실행할 수 있으며,
    • Executor를 종료 시키거나, 여러 Callable을 동시에 실행하는 등의 기능을 제공한다.
    • ScheduledExecutorService: ExecutorService를 상속 받은 인터페이스로 특정 시간 이후에 또는 주기적으로 작업을 실행할 수 있다

     

     

    실습하기


     ExecutorService 로 작업 실행하기

    싱글 쓰레드로 구현

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
      public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.submit(new Runnable() {
          @Override
          public void run() {
            System.out.println("Thread : " + Thread.currentThread().getName());
          }
        });
        
        // 명시적으로 종료해주어야 한다. (graceful shutdown, 현재 진행중인 작업은 끝까지 마치고 끝낸다.)
        executorService.shutdown(); 
      }
    }

     

    여러개의 쓰레드를 주어 구현

    package com.example.reactivestreamstoby;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
      public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(getRunnable("item-1"));
        executorService.submit(getRunnable("item-2"));
        executorService.submit(getRunnable("item-3"));
        executorService.submit(getRunnable("item-4"));    
        executorService.submit(getRunnable("item-5"));
    
        executorService.shutdown();
      }
    
      private static Runnable getRunnable(String msg) {
        return () -> System.out.println(msg + " " + Thread.currentThread().getName());
      }
    }
    // 결과
    // Hi pool-1-thread-1
    // Hello pool-1-thread-2
    // Nice meet u pool-1-thread-1
    // :-) pool-1-thread-1

     

    위 코드는 아래와 같이 처리된다. 

    쓰레드 풀에 있는 쓰레드는 데이터를 받아 처리하고, 나머지 데이터는 큐에 대기하고 있는 형태이다.

    (내부적으로 쓰레드 풀을 사용하는 이유는 쓰레드를 생성하는데 비용이 덜 들기 때문이다.)

     

    Scheduled 사용하기 

    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class Main {
      public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        // 3초 이따가 실행 (단 한번 실행)
        executorService.schedule(getRunnable("item-1"), 3, TimeUnit.SECONDS);
        executorService.shutdown();
    
        // 반복적으로 실행하고 싶은 경우 ( 2초 마다 반복 실행)
        //executorService.scheduleAtFixedRate(getRunnable("item-1"), 1,2, TimeUnit.SECONDS);
      }
    
      private static Runnable getRunnable(String msg) {
        return () -> System.out.println(msg + " " + Thread.currentThread().getName());
      }
    }

     

     

    ExecutorService로 멈추기

    executorService.shutdown(); // 처리중인 작업 기다렸다가 종료
    executorService.shutdownNow(); // 당장 종료

     

     

     

    Fork/Join 프레임워크

    • ExecutorService의 구현체로 손쉽게 멀티 프로세서를 활용할 수 있게끔 도와준다.

     

     

     

    참고 


    '프로그래밍 > Java' 카테고리의 다른 글

    CompletableFuture (5)  (0) 2022.05.06
    CompletableFuture (4)  (0) 2022.05.06
    CompletableFuture (1) - 자바 Concurrent 프로그래밍 소개  (0) 2022.05.06
    Date와 Time API  (0) 2022.05.05
    Optional  (0) 2022.05.05
Designed by Tistory.