Características: La estructura de datos subyacente es una matriz; ordenada; hilo no seguro;
Array ---> La longitud de la tabla de búsqueda y adición y suma es O (1), la inserción y eliminación de elementos es O (n);
El tamaño de inicialización es 10 y el mecanismo de expansión es expandirse a 1.5 veces la longitud de la matriz original.
El código inseguro del hilo refleja:
// List<String> testArray = new ArrayList<>(); 抛ConcurrentModificationException(并发修改)异常
// List<String> testArray = new Vector<>(); //线程安全,低效(Synchronized)
// List<String> testArray = Collections.synchronizedList(new ArrayList<>()); //线程安全,低效(Synchronized)
List<String> testArray = new CopyOnWriteArrayList<>();
// 读写分离,ReentrantLock 轻量级锁,上锁,进行数组长度加1的复制,将数据写到复制的数组上,并将原数组失效(即指针指向复制的数组)
for (int i = 0; i < 50 ; i++) {
new Thread(()-> {
testArray.add("aaa");
System.out.println(testArray);
},String.valueOf(i)).start();
}
/**
* Replaces the element at the specified position in this list with the
* specified element.
* CopyOnWriteArrayList类中写操作如何保证线程安全
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock(); // 加锁
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
// 数组的复制
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
// 重新指向新的数组
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock(); //释放锁
}
}
La clase relacionada CopyOnWriteArrayList implicará un concepto:
Copia profunda y copia superficial:
- Copia superficial: pase el valor al tipo de datos básico y copie por referencia al tipo de datos de referencia. Esta es una copia superficial.
- Copia profunda: pase el valor del tipo de datos básico, cree un nuevo objeto para el tipo de datos de referencia y copie su contenido, esta es una copia profunda.
Hay muchas operaciones de copia en el código central
Métodos System.arraycopy () y Arrays.copyOf ()
¿Cuál es la diferencia entre los dos métodos?
System.arraycopy (); necesita la matriz de destino, copie la matriz original en su propia matriz definida, y puede elegir el punto de inicio y la longitud de la copia y la posición de la nueva matriz.
copyOf () es que el sistema crea automáticamente una matriz internamente y devuelve la matriz.
/**
* @param src the source array. 原数组
* @param srcPos starting position in the source array. 原数组开始复制位置
* @param dest the destination array. 复制到的数组
* @param destPos starting position in the destination data. 开始位置
* @param length the number of array elements to be copied. 结束位置
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
...
/**
* original需要复制的数组;newLength需要复制的长度
*/
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
Puntos de conocimiento relacionados de difusión:
La capa inferior de HashSet es HashMap; pero HashSet solo toma la clave de HashMap, y el valor de Value se establece de manera uniforme en una constante Object.
LinkedList estructura de datos subyacente: lista doblemente vinculada