mini-pms 36 b
1 minute read
Server
36-b. 스레드풀을 이용하여 스레드를 재사용하기 : 자바에서 제공하는 스레드풀 사용하기
01) 기존의 ThreadPool 대신에 ExecutorService 를 사용한다.
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("서버 종료!");
}
.
.
.
}