수업 시간에 멀티채팅 프로그램을 만드는 실습을 진행했는데 그 때 발생한 ConcurrentModificationException과 클라이언트 퇴장시 계속해서 Null을 출력하는 현상을 해결한 과정을 정리해 보고자한다.
✅ 발생 상황1
채팅 프로그램에 참여하고 있던 사용자가 나갔을 때 ConcurrentModificationException이 발생
문제 원인
멀티스레드 환경에서 하나의 리스트에 접근하려고 했을 때 그 리스트가 동기화처리가 되지 않는 리스트라면 ConcurrentModificationException가 발생한다.
해결 방법
리스트에 동기화 처리해주면 된다.
수정 전
userList = new ArrayList<>();
수정 후
userList = Collections.synchronizedList(new ArrayList<>());
✅ 발생 상황2
클라이언트가 나갔을 때 계속해서 나간 클라이언트가 null을 반환하는 상황
문제 원인
BufferedReader의 readLine()은 스트림의 끝에 가면 null값을 입력받는다. 클라이언트가 나가면 스트림의 끝이라고 판단하기 때문에 계속해서 null을 반환한 것
해결 방법
null 체크를 해주었다.
@Override
public void run() {// start! 스레드 업무 시작!
try {
nickname = br.readLine();// 일단 이 사용자 메시지 오기전에 가장 첫 메시지를 닉네임으로 쓰기
broadcast(nickname + "님이 입장하셨습니다.");
while (true) {// 내가 담당하는 사용자의 메시지를 계속 듣고 있기
String msg = br.readLine();
if (msg == null) break;// 이곳 추가
broadcast("[" + nickname + "]: " + msg);
}
} catch (IOException e) {
removeUser(this);// 퇴장 시 유저 스레드를 리스트에서 지워주세요라고 서버에 부탁
} finally {
try {
socket.close();// 소켓 닫기
} catch (IOException e) {
e.printStackTrace();
}
removeUser(this);// 퇴장 시 유저 스레드를 리스트에서 제거
broadcast(nickname + "님이 퇴장하셨습니다.");
}
}