一、傳統集合類在併發訪問時的問題說明java
二、傳統方式下用Collections工具類提供的synchronizedCollection方法來得到同步集合,分析該方法的實現源碼。安全
三、傳統方式下的Collection在迭代集合時,不容許對集合進行修改。併發
> 根據AbstractList的checkForComodification方法的源碼,分析產生ConcurrentModificationException異常的緣由。app
四、Java5中提供了以下一些同步集合類ide
經過看java.util.concurrent包下的介紹能夠知道有哪些併發集合工具
> ConcurrentHashMap ui
> CopyOnWriteArrayList this
> CopyOnWriteArraySetspa
package com.lh.threadtest.t14; /*** * * @ClassName: User * @Description: TODO * @author Liu * @date 2018年1月18日 下午8:43:50 * */ public class User implements Cloneable { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof User)) { return false; } User user = (User) obj; // if(this.name==user.name && this.age==user.age) if (this.name.equals(user.name) && this.age == user.age) { return true; } else { return false; } } public int hashCode() { return name.hashCode() + age; } public String toString() { return "{name:'" + name + "',age:" + age + "}"; } public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException e) { } return object; } public void setAge(int age) { this.age = age; } public String getName() { return name; } }
package com.lh.threadtest.t14; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /*** * * @ClassName: CollectionTest * @Description: TODO * @author Liu * @date 2018年1月18日 下午8:44:27 * */ public class CollectionTest { public static void main(String[] args) { Collections.synchronizedCollection(null); // Collection users = new ArrayList(); Collection users = new CopyOnWriteArrayList(); users.add(new User("張三", 28)); users.add(new User("李四", 25)); users.add(new User("王五", 31)); Iterator itrUsers = users.iterator(); while (itrUsers.hasNext()) { User user = (User) itrUsers.next(); if ("張三".equals(user.getName())) { users.remove(user); // itrUsers.remove(); } else { System.out.println(user); } } } }
private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable { private static final long serialVersionUID = 1978198479659022715L; private final Map<K,V> m; // Backing Map final Object mutex; // Object on which to synchronize SynchronizedMap(Map<K,V> m) { this.m = Objects.requireNonNull(m); mutex = this; } SynchronizedMap(Map<K,V> m, Object mutex) { this.m = m; this.mutex = mutex; } public int size() { synchronized (mutex) {return m.size();} } public boolean isEmpty() { synchronized (mutex) {return m.isEmpty();} } public boolean containsKey(Object key) { synchronized (mutex) {return m.containsKey(key);} } public boolean containsValue(Object value) { synchronized (mutex) {return m.containsValue(value);} } public V get(Object key) { synchronized (mutex) {return m.get(key);} } public V put(K key, V value) { synchronized (mutex) {return m.put(key, value);} } public V remove(Object key) { synchronized (mutex) {return m.remove(key);} } public void putAll(Map<? extends K, ? extends V> map) { synchronized (mutex) {m.putAll(map);} } public void clear() { synchronized (mutex) {m.clear();} } private transient Set<K> keySet; private transient Set<Map.Entry<K,V>> entrySet; private transient Collection<V> values; public Set<K> keySet() { synchronized (mutex) { if (keySet==null) keySet = new SynchronizedSet<>(m.keySet(), mutex); return keySet; } } public Set<Map.Entry<K,V>> entrySet() { synchronized (mutex) { if (entrySet==null) entrySet = new SynchronizedSet<>(m.entrySet(), mutex); return entrySet; } } public Collection<V> values() { synchronized (mutex) { if (values==null) values = new SynchronizedCollection<>(m.values(), mutex); return values; } } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) {return m.equals(o);} } public int hashCode() { synchronized (mutex) {return m.hashCode();} } public String toString() { synchronized (mutex) {return m.toString();} } // Override default methods in Map @Override public V getOrDefault(Object k, V defaultValue) { synchronized (mutex) {return m.getOrDefault(k, defaultValue);} } @Override public void forEach(BiConsumer<? super K, ? super V> action) { synchronized (mutex) {m.forEach(action);} } @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { synchronized (mutex) {m.replaceAll(function);} } @Override public V putIfAbsent(K key, V value) { synchronized (mutex) {return m.putIfAbsent(key, value);} } @Override public boolean remove(Object key, Object value) { synchronized (mutex) {return m.remove(key, value);} } @Override public boolean replace(K key, V oldValue, V newValue) { synchronized (mutex) {return m.replace(key, oldValue, newValue);} } @Override public V replace(K key, V value) { synchronized (mutex) {return m.replace(key, value);} } @Override public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);} } @Override public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);} } @Override public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { synchronized (mutex) {return m.compute(key, remappingFunction);} } @Override public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { synchronized (mutex) {return m.merge(key, value, remappingFunction);} } private void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) {s.defaultWriteObject();} } }
一、傳統的ArrayList/ArraySet/HashMap集合類線程不安全的緣由?線程
二、ConcurrentModificationException異常發生的緣由?