List集合:
package com.unsafe; import java.util.ArrayList; import java.util.UUID; public class ListTest { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); for (int i = 0; i <20 ; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(list); },String.valueOf(i)).start(); } } }
在这样并发的情况下,ArrayList是不安全的,系统会报ConcurrentModificationException(并发修改异常),解决方案:
package com.unsafe; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; public class ListTest { public static void main(String[] args) { /*并发情况下ArrayList是不安全的,解决方案 1.List<String> list = Collections.synchronizedList(new ArrayList<>()); 2.List<String> list = new CopyOnWriteArrayList<>(); * */ List<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i <20 ; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(list); },String.valueOf(i)).start(); } } }
set集合不安全解决方法与以上类似
HashMap不安全
package com.unsafe; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class MapTest { public static void main(String[] args) { //HashMap默认有初始化容量和负载因子,初始化容量为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,3)); System.out.println(map); }).start(); } } }
多线程的情况下使用HashMap同样会报错ConcurrentModificationException(并发修改异常),所以并发情况下用ConcurrentHashMap。
并发下的HashMap,HashMap是线程不安全的,虽然HashTable可以代替HashMap,达到线程安全的目的,但是HashTable是用一个全局锁来同步不同的线程,这样性能就大大降低了,而ConcurrentHashMap用volatile修饰变量保证了安全高效的读操作,而利用锁分段技术保证了高并发情况下的写操作。
package com.unsafe; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class MapTest { public static void main(String[] args) { //HashMap默认有初始化容量和负载因子,初始化容量为16,负载因子0.75,当数据达到总容量*负载因子时就要进行扩容 Map<String,String> map = new ConcurrentHashMap<>(); for (int i = 0; i <30 ; i++) { new Thread(()->{ map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,3)); System.out.println(map); }).start(); } } }