리액터 패턴
리액터 패턴
이벤트 처리(event handling) 디자인 패턴이다. JAVA TCP 통신에서 클라이언 수 만큼 Thread를 생성한다.
생성된 Thread에서 동시에 여러개의 요청이 들어올 경우 context switching이 빈번히 발생하게 되는데 리액터 패턴은
event handler에게 역할을 위임하여 이러한 문제를 해결한다.
에코 채팅 서버
public class Main {
public static final int PORT = 5000;
public void main(String[] args) {
Reactor reactor = new Reactor(PORT);
reactor.registerHandler(new ReactorEventHandler());
reactor.startServer();
}
}
public class Reactor {
private ServerSocket serverSocket;
private HandleMap handleMap;
public Reactor(int port) {
handleMap = new HandleMap();
try {
serverSocket = new ServerSocket(port);
} catch (IOException e){
e.printStackTrace();
}
}
public void startServer() {
ThreadPoolDispatcher dispatcher = new ThreadPoolDispatcher();
dispatcher.dispatch(serverSocket, handleMap);
}
public void registerHandler(EventHandler handler) {
handleMap.put(handler.getHandler(), handler);
}
public void removeHandler(EventHandler handler) {
handleMap.remove(handler.getHandler());
}
}
public interface Dispatcher {
public void dispatch(ServerSocket serverSocket, HandleMap handleMap);
}
public class HandleMap extends HashMap<String, EventHandler> {
private static final long serialVersionUID = 1L;
}
public class Demultiplexer implements Runnable {
private final int HEADER_SIZE = 6;
private Socket socket;
private HandleMap handleMap;
public Demultiplexer(Socket socket, HandleMap handleMap) {
this.socket = socket;
this.handleMap = handleMap;
}
@Override
public void run() {
InputStream inputStream = null;
try {
byte[] headerBuffer = new byte[HEADER_SIZE];
inputStream = socket.getInputStream();
inputStream.read(headerBuffer);
String header = new String(headerBuffer);
handleMap.get(header).handleEvent(inputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class ThreadPoolDispatcher implements Dispatcher {
static final String NUM_THREADS = "8";
static final String THREAD_PROP = "Threads";
private int numThreads;
public ThreadPoolDispatcher() {
numThreads = Integer.parseInt(System.getProperty(THREAD_PROP, NUM_THREADS));
}
@Override
public void dispatch(final ServerSocket serverSocket, final HandleMap handleMap) {
for (int idx_thread = 0; idx_thread < (numThreads - 1); idx_thread++) {
Thread thread = new Thread() {
public void run() {
dispatchLoop(serverSocket, handleMap);
}
};
thread.start();
}
dispatchLoop(serverSocket, handleMap);
}
private void dispatchLoop(ServerSocket serverSocket, HandleMap handleMap) {
while (true) {
try {
Socket socket = serverSocket.accept();
Demultiplexer demultiplexer = new Demultiplexer(socket, handleMap);
Thread thread = new Thread(demultiplexer);
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}