첫 번째는 ArrayList입니다.
이번에는 컬렉션의 불안정성에 대해 설명하겠습니다. 우선 우리 모두 ArrayList를 알고 있습니다!
먼저 몇 가지 지식 포인트를 확장합니다 .ArrayList의 맨 아래 계층은 Object 유형의 배열입니다. 초기 용량은 10 (jdk7 이전, jdk8이 null 참조 후, 지연로드 메커니즘과 유사하게 추가 후 10이 됨) 및 확장 방법입니다. 각 확장은 이전 확장의 절반입니다. 예를 들어 10은 15로 확장되고 15는 22로 확장됩니다. 확장에 사용되는 방법은 Arrays의 복사 방법입니다. OK를 누른 다음 주제를 입력합니다.
이 코드를 먼저보십시오.
List<String> list=new ArrayList<>();
그런 다음 Lambda 표현식을 사용하여 여러 스레드를 생성합니다.
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
예외는 나중에보고 될 것입니다 :
java.util.ConcurrentModificationException 동시 수정 예외의
원인 : 균일 한 자원에 대한 다중 스레드 동시성 경쟁, 잠금 없음
그래서 우리는 어떤 해결책 을 가지고 있습니까? ?
방법 1 :
List<String> list = new Vector<>();
벡터 수집, 하단 레이어는 add 메서드에 동기화 (재 잠금)를 추가합니다. 동시에 스레드가 하나만있어 비효율적이므로 수집이 비효율적이고 안전합니다.
방법 2 :
Collections.synchronizedList(new ArrayList<>());
이것은 ArrayList를 전달하는 Connections의 정적 메소드입니다.
방법 3 :
List<String> list = new CopyOnWriteArrayList<>();
이 JUC 패키지의 클래스는 List 인터페이스를 구현합니다.
맨 아래 계층 : 휘발성 Object [] 배열
의 add 메서드에 ReentrantLock 잠금이 있습니다 .
public boolean add(E e) {
final ReentrantLock lock = this.lock; //加锁
lock.lock();
try {
Object[] elements = getArray(); //先得到老版本的集合
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
**
그런 다음 Set 컬렉션을 살펴 봅니다.
동일한 확장 지식 포인트, HashSet의 기본 데이터 구조는 HashMap (소스 코드 생성자의 new HashMap ())이며, add 메서드는 실제로 map.put (e, PRESENT ) == null을 반환합니다 . PRESENT는 실제로 항상 켜져있는 객체입니다. 따라서 실제로 HashMap의 키입니다.
동일한 단계 :
Set<String> set=new HashSet<>();
for(int i=0;i<30;i++){
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(set);
},String.valueOf(i)).start();
}
동일한 오류 :
java.util.ConcurrentModificationException
솔루션 :
방법 1 :
Set<String> set=Collections.synchronizedSet(new HashSet<>());
방법 2 :
Set<String> set=new CopyOnWriteArraySet();
또한 JUC의 클래스이며 생성자는 실제로 new CopyOnWriteArrayList ();
다음은 우리의지도입니다.
확장 된 지식 : HashMap의 맨 아래 계층 (정렬되지 않고 반복 없음)은 배열 + 연결 목록 (단방향) + 빨강-검정 트리, HashMap은 노드를 저장하고 노드는 Key-Value를 저장합니다. HashMap의 초기 용량은 16이고 부하율은 0.75 ( 16 * 0.75에 도달하면 용량을 확장하면 초기 용량 및 부하율은 시공자를 통해 변경할 수 있으며 원래 용량은 매번 두 배가됩니다.
Map<String, String> map = new HashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
동일한 오류가보고됩니다.
java.util.ConcurrentModificationException
솔루션 :
Map<String, String> map = new ConcurrentHashMap();
JUC 패키지 아래.
이번에 설명한 JUC 컬렉션은 안전하지 않습니다. 도움이 되었으면 좋겠습니다. 더 좋은 제안이 있으면 메시지를 남겨주세요!