集合类的线程不安全问题

ArrayList线程不安全

public class ListTest {
    public static void main(String[] args) {
        List list = new ArrayList();
       
        for (int i = 1; i <= 10; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }).start();
        }
    }
}

运行结果:



从运行结果来看,在多线程并发的情况下使用ArrayList是极其不安全的,它会引发java.util.ConcurrentModificationException 并发修改异常,那该如何避免这种线程不安全的问题呢?

解决方案:

  • List list = new Vector();多线程并发下使用Vector替代ArrayList。
  • List list = Collections.synchronizedList(new ArrayList<>());使用Collections工具类对ArrayList做处理。
  • List list = new CopyOnWriteArrayList();使用JUC下的CopyOnWriteArrayList类实现。
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class ListTest {
    public static void main(String[] args) {
        //List list = new ArrayList();
        //List list = new Vector();
        //List list = Collections.synchronizedList(new ArrayList<>());
        List list = new CopyOnWriteArrayList();

        for (int i = 1; i <= 10; i++){
            //java.util.ConcurrentModificationException 并发修改异常
            //并发下 ArrayList是不安全的
            /**
             * 解决方案:
             * 1.List list = new Vector();
             * 2.List list = Collections.synchronizedList(new ArrayList<>());
             * 3.List list = new CopyOnWriteArrayList();*/
            //CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }).start();
        }
    }
}

HashSet线程不安全

public class SetTest {
    public static void main(String[] args) {
        Set set = new HashSet();

        for (int i = 1; i <= 10; i++){
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

运行结果:



不出所料,依旧出现了java.util.ConcurrentModificationException 并发修改异常,同理,我们也有针对set的线程安全解决方案。

解决方案:

  • Set set = Collections.synchronizedSet(new HashSet<>());
  • Set set = new CopyOnWriteArraySet();
public class SetTest {
    public static void main(String[] args) {
        //Set set = new HashSet();
        //Set set = Collections.synchronizedSet(new HashSet<>());
        Set set = new CopyOnWriteArraySet();

        for (int i = 1; i <= 10; i++){
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

HashMap线程不安全

public class MapTest {
    public static void main(String[] args) {
        //1.Q:Map map = new HashMap();是这样用的吗?A:不是。
        //2.Q:Map map = new HashMap();默认等价于什么?A:new HashMap(16,0.75)
        Map map = new HashMap<>();

        for (int i = 1; i <= 10 ; i++){
            new Thread(()->{
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
                System.out.println(map);
            },String.valueOf(i)).start();
        }

    }
}

运行结果:



不出所料,依旧出现了java.util.ConcurrentModificationException 并发修改异常,同理,我们也有针对Map的线程安全解决方案。

解决方案:

  • Map map = Collections.synchronizedMap(new HashMap<>());
  • Map map = new ConcurrentHashMap<>();

你可能感兴趣的:(集合类的线程不安全问题)