Blog

트러블 슈팅: 책나눔 이벤트 간 연관관계 삭제 중 `ConcurrentModificationException` 발생

tag
트러블슈팅
날짜
2023/10/18
생성 일시
2023/10/28 06:39
작성자

문제 상황

도서와 나눔 이벤트 간의 연관 관계를 삭제하는 과정에서 ConcurrentModificationException이 발생하였다. 이 오류는 컬렉션을 순회하는 동안 해당 컬렉션의 구조가 변경될 때 발생한다.

원인

bookDonationEvent.getBooks().stream().forEach(book->{ book.changeStatus(BookStatusEnum.POSSIBLE); book.removeBookApplyDonation(); });
Java
복사
코드에서 bookDonationEvent.getBooks().forEach() 를 사용하여 도서 리스트를 순회하면서 각 도서의 상태를 변경하고 연관 관계를 제거하는 bookDonationEvent.removeBook(book)를 호출하였다. 이 때문에 순회 중인 리스트의 구조가 변경되면서 ConcurrentModificationException이 발생하였다.

해결 방법

일반 for문 사용하여 해결한다. 리스트의 크기를 미리 얻어와서 반복하는 동안 해당 리스트의 구조가 변경되지 않도록 처리할 수 있다. 그러나 리스트의 중간 요소를 삭제할 때 인덱스의 변화를 주의해야 한다. 이를 해결하기 위해 가장 끝부터 for문을 반복하면 해결이 가능하다.
/** * 연관 관계 삭제 * 도서와 나눔 이벤트 간의 연관 관계 삭제 */ int bookSize = bookDonationEvent.getBooks().size(); for (int i = bookSize - 1; i >= 0; i--) { bookDonationEvent.getBooks().get(i).changeStatus(BookStatusEnum.POSSIBLE); bookDonationEvent.removeBook(bookDonationEvent.getBooks().get(i)); } /** * 도서와 나눔 신청 간의 연관 관계 삭제 */ int applysize = bookDonationEvent.getBookApplyDonations().size(); for (int i = applysize - 1; i >= 0; i--) { Book book = bookRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getBook().getBookId()).orElseThrow( () -> new IllegalArgumentException("해당 책이 존재하지 않습니다.") ); BookApplyDonation bookApplyDonation = bookApplyDonationRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getApplyId()).orElseThrow( () -> new IllegalArgumentException("해당 신청이 존재하지 않습니다.") ); bookApplyDonation.removeBook(book); int a; }
Java
복사

정리

컬렉션을 순회하면서 동시에 해당 컬렉션의 구조를 변경할 때는 ConcurrentModificationException이 발생할 위험이 있다.