JAVA 높은 동시성 (JUC) 수집은 안전하지 않습니다.

첫 번째는 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 컬렉션은 안전하지 않습니다. 도움이 되었으면 좋겠습니다. 더 좋은 제안이 있으면 메시지를 남겨주세요!

추천

출처blog.csdn.net/Pzzzz_wwy/article/details/105960684