Home  >  Article  >  Java  >  How to ensure the thread safety of ArrayList, HashSet and HashMap in Java's high-concurrency multi-thread environment?

How to ensure the thread safety of ArrayList, HashSet and HashMap in Java's high-concurrency multi-thread environment?

王林
王林forward
2023-05-09 22:49:071639browse

1.Thread-unsafe solution for ArrayList

Open the first line of comments in the main method and execute it a few times. You will see exception information as shown below:???

How to ensure the thread safety of ArrayList, HashSet and HashMap in Javas high-concurrency multi-thread environment?

This is a concurrent modification exception. First of all, ArrayList is definitely thread-unsafe. The reason for this exception is that the first thread may have just entered the ArrayList collection to perform an add operation. In addition, At this time, one thread also came in to perform the add operation, and the third thread came in to perform the get operation. As a result, the reading and writing could not be synchronized, and the result finally exploded when printing.

Solution Look at the remaining lines of comments in the code.

package test.notsafe;
 
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
 
/**
 * 演示ArrayList的线程不安全问题及解决方案
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        //List<String> list = new ArrayList<>();
 
        //解决方法1:使用Vector
        //List<String> list = new Vector<>();
 
        //解决方法2:Collections
        //List<String> list = Collections.synchronizedList(new ArrayList<>());
 
        //解决方法3:CopyOnWriteArrayList
        List<String> list = new CopyOnWriteArrayList<>();
 
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

How to ensure the thread safety of ArrayList, HashSet and HashMap in Javas high-concurrency multi-thread environment?

A simple explanation about how CopyOnWriteArrayList solves the thread insecurity problem: Just look at the add(E e) method in the source code:

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();
        }
    }

This CopyOnWriteArrayList is in Before performing the add operation, lock it first, then obtain the original ArrayList collection container through getArray(), and then call the Arrays.copyOf method to copy the original container into a new container, because it needs to be added (the length is naturally 1). Then add elements to this new container. After the addition is completed, call the setArray method to point the reference of the original container to this new container. Then the advantage of doing this is: add elements in a new container, whatever the original container should be, and if other threads want to get and read elements, they still read from the original container (that is, multiple threads can read concurrently); and If other threads want to add, they have to wait for other threads to complete and then point the reference of the original container to the new container.

CopyOnWrite containers are two different containers when it comes to reading and writing, and the idea of ​​separation of reading and writing is also used.

2. Thread-unsafe solution for HashSet

If it is a new HashSet here, the same concurrent modification exception as the ArrayList above may still occur. See the comments in the code for the solution.

package test.notsafe;
 
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
 
/**
 * 演示HashSet的线程不安全问题及解决方案
 */
public class ThreadDemo3 {
    public static void main(String[] args) {
        //Set<String> set = new HashSet<>();
 
        //解决方法1:Collections
        //Set<String> set = Collections.synchronizedSet(new HashSet<>());
 
        //解决方法2:CopyOnWriteArraySet
        Set<String> set = new CopyOnWriteArraySet<>();
 
        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

3. Thread-unsafe solution for HashMap

package test.notsafe;
 
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
 
/**
 * 演示HashMap的线程不安全问题及解决方案
 */
public class ThreadDemo4 {
    public static void main(String[] args) {
        //Map<String,Object> map = new HashMap<>();
 
        //解决方法1:Collections
        //Map<String,Object> map = Collections.synchronizedMap(new HashMap<>());
 
        //解决方法2:ConcurrentHashMap
        Map<String,Object> map = new ConcurrentHashMap<>();
 
        for (int i = 0; i < 10; i++) {
            String key = String.valueOf(i);
            new Thread(() -> {
                map.put(key,UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

The above is the detailed content of How to ensure the thread safety of ArrayList, HashSet and HashMap in Java's high-concurrency multi-thread environment?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete