Vector
public class Vector<E> {
// 모든 메서드가 synchronized
public synchronized boolean add(E e) { ... }
public synchronized E get(int index) { ... }
public synchronized E set(int index, E element) { ... }
public synchronized E remove(int index) { ... }
}
상황별 추천
단일 스레드 → ArrayList
List<User> users = new ArrayList<>(); // 가장 빠름
멀티스레드, 읽기/쓰기 균등 → synchronizedList
List<Task> tasks = Collections.synchronizedList(new ArrayList<>());
synchronized(tasks) {
if (!tasks.isEmpty()) {
Task task = tasks.remove(0);
}
}
멀티스레드, 읽기 중심 → CopyOnWriteArrayList
List<Config> configs = new CopyOnWriteArrayList<>(); // 읽기 빠름, 쓰기 느림
고성능 멀티스레드 → ConcurrentLinkedQueue
Queue<Message> messages = new ConcurrentLinkedQueue<>(); // Queue 용도로
Vector를 피하는 이유
// 1. 불필요한 동기화 비용
Vector<String> vector = new Vector<>();
String item = vector.get(0); // 단일 스레드여도 동기화 비용
// 2. 복합 연산 불안전
if (!vector.isEmpty()) {
vector.remove(0); // 여전히 동기화 필요
}
// 3. 큰 확장 비율 (2배) // 메모리 낭비 가능성
- 실제 코드 예시
```java
안전하지 않은 ArrayList
List
list = new ArrayList<>();
// 스레드 1 new Thread(() -> { for(int i = 0; i < 1000; i++) { list.add(i); } }).start();
// 스레드 2
new Thread(() -> {
for(int i = 1000; i < 2000; i++) {
list.add(i); // Race Condition! 데이터 손실 가능
}
}).start();
synchronizedList 사용
javaList
// 스레드 1 new Thread(() -> { for(int i = 0; i < 1000; i++) { list.add(i); // 안전 } }).start();
// 스레드 2 new Thread(() -> { for(int i = 1000; i < 2000; i++) { list.add(i); // 안전 } }).start();
// 반복 시에는 수동 동기화 synchronized(list) { for(Integer num : list) { System.out.println(num); } } ```
Q2: 멀티스레드 환경에서 안전한 List는? A: “Collections.synchronizedList(), CopyOnWriteArrayList, Vector 등이 있습니다. 읽기/쓰기가 균등하면 synchronizedList, 읽기 중심이면 CopyOnWriteArrayList를 주로 사용합니다. 복합 연산 시에는 수동 동기화가 필요합니다.” Q3: Collections.synchronizedList()와 Vector 차이점은? A: “Vector는 메서드 레벨에서 동기화하고, synchronizedList는 객체 레벨에서 동기화합니다. 성능상 synchronizedList가 더 유연하고, Vector는 불필요한 동기화 비용이 있어서 Legacy로 분류됩니다. 둘 다 복합 연산에서는 추가 동기화가 필요합니다.” 핵심: Vector는 Legacy, 실무에서는 synchronizedList 사용, 복합 연산은 수동 동기화 필요!