1、Map
为防止多线程环境中使用HashMap出现问题,需要保证线程安全,可以使用Collections工具类下得synchronizedMap()方法:
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<>(m);
}
返回的SynchronizedMap是Collections的私有静态内部类,使用委托,将所有map相关的功能交由传入的HashMap实现,而它只负责保证线程安全(使用synchronized关键字对所有操作加mutex锁),以下是部分源码:
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();}
}
...
}
虽然可以满足线程安全要求,但性能因为mutex的锁原因不算太好;
如果并发级别不高,一般可以使用,但在高并发环境中,可以使用ConcurrentHashMap类;
2、List
ArrayList和Vector都使用数组作为内部实现,但Vector是线程安全的,而ArrayList不是;
LinkedList使用链表结构实现了List,但不是线程安全的;
可以使用Collections.synchronizedList()方法来包装List:
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
与上面讲到的线程安全的Map类似,区别在于ArrayList和Vector实现了RandomAccess,而LinkedList没有实现,底层还是一样的:
static class SynchronizedRandomAccessList<E> extends SynchronizedList<E> implements RandomAccess
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
...
}