"문제가 생긴다면 바로 죽여라"
ConcurrentModificationException을 던져, 이상한 상태로 진행되는 것을 방지import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class FailFastIteratorExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
// 컬렉션을 직접 수정 → fail fast
if ("banana".equals(value)) {
list.remove(value); // 여기서 ConcurrentModificationException 발생
}
}
}
}
"문제가 생겨도 최대한 안전하게 계속 돌아가게 하라"
CopyOnWriteArrayList나 ConcurrentHashMap같은 concurrent 컬렉션에서 구현되고, 이들은 복사본(snapshot)을 만들어 순회하므로 원본 수정이 순회에 영향을 주지 않음import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class FailSafeExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
// 순회 중 원본 리스트 수정 → 예외 발생 안 함 (fail safe)
if ("banana".equals(value)) {
list.add("orange"); // snapshot 기반 순회라 문제없음
}
}
System.out.println("Final list: " + list); // [apple, banana, cherry, orange]
}
}
ArrayList로 구조 변경 탐지)Objects.requireNonNull, @NotNull로 null 체크)CopyOnWriteArrayList)| 활용 시나리오 | Fail Fast | Fail Safe |
|---|---|---|
| 개발/디버깅 | ✅ 이상 징후 즉시 발견 | ❌ 변경 무시로 버그 숨김 |
| 멀티스레드 | ❌ ConcurrentModificationException | ✅ 예외 없이 안전 동작 |
| 읽기:쓰기 비율 | 균형 | 읽기 >> 쓰기 |
| 성능 특성 | 읽기/쓰기 빠름 | 읽기 빠름, 쓰기 느림 |
Fail Fast -> 테스트 우선
Fail Safe -> 운영 우선
각 기능을 알고 사용하자💡