Collections中的工具方法
public static <T> Collection<T> synchronizedCollection(Collection<T> c)(获得一个Collection安全集合)
public static <T> List<T> synchronizedList(List<T> list)(获得一个List安全集合)
public static <T> Set<T> synchronizedSet(Set<T> s)(获得一个Set安全集合)
public static <K , V> Map<K , V> synchronizedMap(Map<K , V> m)(获得一个Map安全集合)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
public static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m)
JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchronized实现
用public static <T> List<T> synchronizedList(List<T> list)举例:
创建方式
List<String> li = new ArrayList<String>();
List<String> list = Collections.synchronizedList(li);
返回一个新的List类型的集合对象
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
子类构造方法
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
父类构造方法
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);//非空判断
mutex = this;
}
final Object mutex
final Collection<E> c
用Final Object mutex作为同步代码块的对象,进行加锁,保证线程安全
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
CopyOnWtiteArrayList
线程安全的ArrayList,加强版读写分离
写有锁,读无锁,读写之间不阻塞,优于读写锁
写入时,先copy一个容器副本、在添加新元素,最后替换引用
使用方式与ArrayList无异
List<String> list = new CopyOnWriteArrayList<String>();
写有锁
都将底层数组做了一次复制,写的是新数组,完成赋值后,再将新数组替换掉旧数组!
每调用一次,底层方法扩容一次!
public boolean add(E e) {
final ReentrantLock lock = this.lock;//将原来建好的锁赋值给变量,
lock.lock(); //获取锁 相当于建了一个新锁
try {
Object[] elements = getArray();//获得一个数组
int len = elements.length;//数组的长度,初始为0
Object[] newElements = Arrays.copyOf(elements, len + 1);//扩容操作
newElements[len] = e;//将新数组的下标0存入传过来的e
setArray(newElements);//将新创建的数组调用setArray
return true;//成功返回true
} finally {
lock.unlock();//释放锁
}
}
其中用到的方法:
private transient volatile Object[] array;
final Object[] getArray() {
return array;
}
返回一个存好array数组
final void setArray(Object[] a) {
array = a;
}
将传过来的数组存入array
读无锁
读的是写操作完成之前的旧数组!写完之后,才能读到的新数组的新值
public E get(int index) {
return get(getArray(), index);
}
final Object[] getArray() {
return array;
}
返回一个array数组
private E get(Object[] a, int index) {
return (E) a[index];
}
返回一个数组index下标的值