Próbuję przekonwertować linkList na ArrayList, jak pokazano poniżej.
private LinkedList<myData> myLinkedList= new LinkedList<myData>();
public Collection<myData> getData()
{
return new ArrayList<myData>(myLinkedList);
}
LinkList może być aktualizowany przez wiele wątków. Podczas testowania w produkcji pojawia się poniższy błąd. Błąd nie jest zgodny. Więc dostaję to może być raz na tydzień, miesiąc albo tak.
java.lang.ArrayIndexOutOfBoundsException: 15
at java.util.LinkedList.toArray(LinkedList.java:866)
at java.util.ArrayList.<init>(ArrayList.java:131)
at org.xxx.yyy.zzz.getData(Data.java:291)
Czy istnieje sposób, w jaki mógłby być powiązany ze współbieżną modyfikacją linkedList. Doceń wszelką pomoc w tym zakresie.
Odpowiedzi:
5 dla odpowiedzi № 1toArray
Upadek jest tylko jeden symptom, że robisz coś fundamentalnie niebezpiecznego.
Jeśli wiele wątków jednocześnie uzyskuje dostęp do połączonej listy, a co najmniej jeden z wątków modyfikuje ją strukturalnie, to musi być zsynchronizowane zewnętrznie.
Będziesz musiał dodać synchronizację (nie tylko dla toArray
, ale w zasadzie wszystkie zastosowania listy) lub użyć jednej z równoległych kolekcji, która jest zaprojektowany być bezpiecznym dla wątków.
2 dla odpowiedzi nr 2
LinkedList#toArray()
jest zaimplementowany jako taki (Oracle JDK 7)
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
Jeśli dodasz do LinkedList
po result
array jest skonstruowany, ale przed for
loop, następnie wyrażenie dostępu do tablicy wewnątrz for
pętla spowoduje ArrayIndexOutOfBoundsException
podczas próby uzyskania dostępu do indeksu większego niż oryginał size
.
Powinieneś naprawdę wprowadzić pewne bariery synchronizacji, aby tak się nie stało.