📌스레드 병렬 처리
연결 수락을 위해 ServerSocket의 accept()을 실행하거나, 서버 연결 요청을 위해 socket 생성자 또는 connect()를 실행할 경우에는 해당 작업이 완료되기 전까지 블로킹(blocking)된다. 데이터 통신을 할 때에도 마찬가지인데 InputStream의 read() 메소드는 상대방이 데이터를 보내기 전까지 블로킹되고, OutputStream의 wrtie() 메소드는 데이터를 완전하게 보내기 전까지 블로킹 된다. 즉 말하고자 하는 바는 ServerSocket과 Socket은 동기(블로킹) 방식으로 구동된다.
만약 서버를 실행시키는 main 스레드가 직접 입출력 작업을 담당하게 되면 입출력이 완료될 때 까지 다른 작업을 할 수 없게 된다. 서버 어플리케이션은 지속적으로 클라이언트의 연결 수락 기능을 수행해야 하는데, 입출력에서 블로킹되면 이 작업을 할 수 없게 된다. 또한 클라이언트1과 서버가 입출력하는 동안은 다른 클라이언트2와 입출력을 할 수 없게 된다. 그렇기 때문에 accept(), connect(), read(), write()는 별도의 작업 스레드를 생성해서 병렬적으로 처리하는 것이 좋다.
하지만 스레드로 병렬 처리를 할 경우, 만약 수천 개의 클라이언트가 서버와 동시에 연결하게 되면 수천개의 스레드가 생성되기 때문에 서버 성능이 급격히 저하되고, 다운되는 현상이 발생할 수 있다. 이러한 문제를 해결하기 위해 스레드풀을 사용하게 되었다.
스레드풀은 그림처럼 작업 처리에 사용되는 스레드를 제한된 개수만큼 정해 미리 생성해둔 다음 작업 큐(Queue)에 들어오는 작업들을 하나씩 스레드가 맡아 처리하게 한다. 스레드 수를 제한해서 사용하기 때문에 갑작스런 클라이언트의 폭증은 작업 큐의 작업량만 증가시킬 뿐 스레드 수는 변함이 없기 때문에 서버 성능은 적게 저하된다. 다만 대기 하는 작업량이 많을 경우 개별 클라이언트에서 응답을 늦게 받을 수 있다.
'Java' 카테고리의 다른 글
[Java] NIO 기반 입출력 - (2)NIO 파일과 디렉토리 (0) | 2022.06.07 |
---|---|
[Java] NIO 기반 입출력 - (1)NIO란? (0) | 2022.06.07 |
[Java] IO 기반 입출력 - (1)입력 스트림과 출력 스트림 (0) | 2022.06.05 |
BufferedReader / BufferWriter (0) | 2022.04.01 |
[Java] 스트림(stream) (0) | 2021.08.07 |