回顾集合相关知识的时候发现,list集合想要保证线程安全除了使用
vector和Class CopyOnWriteArrayList<E>之外还可以通过Collections.synchronizedList()
获取一个线程安全的集合,就看看他具体是如何实现的
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
首先是判断一下是否实现了RandomAccess,这个接口是支持随机访问的,这里可以简单的理解为传入ArrayList和LinkedList(链表结构不支持随机访问)
这里返回了两个集合
SynchronizedRandomAccessList
SynchronizedList
SynchronizedRandomAccessList(List<E> list) {
super(list); //这里指向父级
}
//点进去
SynchronizedList(List<E> list) {
super(list); //又指向父级
this.list = list;
}
//点进去
final Collection<E> c; // Backing Collection
final Object mutex;
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this; //这里就是传传进来的集合作为锁对象
}
super( )的用法
super( ) : super( )其实就相当于一个指向基类的指针,(Java中没有指针,但是可以这样理解)。至于用法有一下三种形式:1. super.XXX( 这里的XXX指的是父类的成员变量名即父类的属性,或者对象名)
2. super.XXX( ) ( 这里的XXX是父类中的其中一个方法名)
3. super( ) ( 这种形式指的是:调用父类没有参数的构造方法(也叫构造函数)注意: 这里super( ) 只能放在子类的构造方法里面,并且只能放在构造方法的首句)
4. super( x,y,z...) (此形式指:调用父类有参数的构造方法,也必须放在子类的构造方法(成员方法不可以)里面,并且只能放在构造方法的首句。其中x,y,z是指的与父类此有参构造方法中参数数据类型相对应的子类中的参数)
到这里是把我们传入的集合作为了锁,接着看他的添加方法
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection<? extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
}
可以看出他的方法,都使用synchronized关键字,这里他与Vector的区别就在这synchronized的位置不同,也就是锁粒度不同,如下图
/**
*
* Vector的add方法
*
*/
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
相对的这种方式获取的线程安全的集合比Vector效率会略高
其本质原理还是通过synchronized来保证的线程安全