mini-pms 36 b

1 minute read

Server

36-b. 스레드풀을 이용하여 스레드를 재사용하기 : 자바에서 제공하는 스레드풀 사용하기

01) 기존의 ThreadPool 대신에 ExecutorService 를 사용한다.

  • util 패키지는 지운다.
public class ServerApp {
  static boolean stop = false;

  // 기존의 ThreadPool 대신 ExecutorService를 사용한다.
  ExecutorService threadPool = Executors.newCachedThreadPool();

  static Map<String,Object> context = new Hashtable<>();

  List<ApplicationContextListener> listeners = new ArrayList<>();

  public void addApplicationContextListener(ApplicationContextListener listener) {
    listeners.add(listener);
  }

  public void removeApplicationContextListener(ApplicationContextListener listener) {
    listeners.remove(listener);
  }

  private void notifyApplicationContextListenerOnServiceStarted() {
    for (ApplicationContextListener listener : listeners) {
      listener.contextInitialized(context);
    }
  }

  private void notifyApplicationContextListenerOnServiceStopped() {
    for (ApplicationContextListener listener : listeners) {
      listener.contextDestroyed(context);
    }
  }

  public void service(int port) {

    notifyApplicationContextListenerOnServiceStarted();

    try (ServerSocket serverSocket = new ServerSocket(port)) {
      System.out.println("서버 실행 중...");

      while (true) {
        Socket clientSocket = serverSocket.accept();

        if (stop) {
          break;
        }

        threadPool.execute(() -> handleClient(clientSocket));
      }

    } catch (Exception e) {
      e.printStackTrace();
    }

    notifyApplicationContextListenerOnServiceStopped();

    threadPool.shutdown();

    // 스레드를 종료시킨다.
    try {
      // 스레드풀의 모든 스레드가 종료될 때까지 기다린다.
      if (!threadPool.awaitTermination(10, TimeUnit.SECONDS)) {
        System.out.println("아직 종료 안된 작업이 있다.");
        System.out.println("남아 있는 작업의 강제 종료를 시도하겠다.");
        // => 만약 10초가 경과될 때까지 종료되지 않으면,
        //    수행 중인 작업을 강제 종료하라고 지시하고,
        //    대기 중인 작업은 취소한다.
        threadPool.shutdownNow();

        // 그리고 다시 작업이 종료될 때까지 기다린다.
        if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
          System.out.println("스레드풀의 강제 종료를 완료하지 못했다.");
        } else {
          System.out.println("모든 작업을 강제 종료했다.");
        }
      }
    } catch (Exception e) {
      System.out.println("스레드풀 종료 중 오류 발생!");
    }
    System.out.println("서버 종료!");
  }
.
.
.
}

Categories:

Updated: