Почему размер arraylist не правильный, когда несколько потоков добавляют элементы в него?
730 просмотра
4 ответа
Почему размер Arraylist не правильный, когда несколько потоков добавляют элементы в него?
threadCount = 100;
List<Object> list = new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread(new MyThread(list, countDownLatch));
thread.start();
}
class MyThread implements Runnable {
// ......
@Override
public void run() {
for (int i = 0; i < 100; i++) {
list.add(new Object());
}
}
}
Когда эта программа завершена, размер списка должен быть 10000. На самом деле, размер может быть 9950, 9965 или некоторые другие числа. Почему?
Я знаю, почему эта программа может подниматься IndexOutofBoundsException
и почему в ней есть некоторые нули, но я просто не понимаю, почему размер неправильный.
Ответы (4)
3 плюса
Я просто не понимаю, почему размер неправильный?
Поскольку ArrayList не является потокобезопасным, два потока могут добавляться с одинаковым индексом. Так что один поток перезаписывает.
Автор: Azodious Размещён: 26.10.2016 09:041 плюс
arraylist не является поточно-ориентированным, поэтому если какая-либо многопотоковая операция над одним объектом arraylist, результат не определен,, что означает, что все может произойти из-за jvm, включая, но не ограничиваясь, неправильный размер, исключение, утечку памяти, как и ожидалось
Автор: dexter Размещён: 26.10.2016 09:320 плюса
Это просто, вы выполняете небезопасную операцию над объектом ... Таким образом, вы не можете предсказать стабильность ... Если вы запустите достаточно раз, может быть один экземпляр, когда list.size () вернет 10000. Почему это не так? возвращаться всегда. Ответ, потому что это не потокобезопасно. Теперь рассмотрим код добавления в arraylist
public boolean add( E element) {
ensureCapacity(size+1); // Increments modCount!!
elementData[index] = element;
return true;
}
Предположим здесь, что когда поток 10 находится внутри «sureCapacity» и переходит в спящий режим, тогда придет другой поток (скажем, поток 11), и они (поток 10 и 11) в конечном итоге вставят 2 элемента в одном месте. Это происходит здесь
Автор: RAHUL ROY Размещён: 26.10.2016 09:170 плюса
Вы должны обратиться к исходному коду в ArrayList.
@Override public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
ArrayList использует System.arraycopy(a, 0, newArray, 0, s)
для вставки элемента. Если запущено несколько потоков, массив полей, содержащий элементы, не является исходным, и его размер меньше ожидаемого.
Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- java Почему я не могу объявить статические методы в интерфейсе?
- arraylist ArrayList в Java и ввод
- arraylist Создать ArrayList из массива
- arraylist Как удалить повторяющиеся элементы из ArrayList?
- arraylist Когда использовать LinkedList поверх ArrayList в Java?
- arraylist Как посчитать количество вхождений элемента в список
- arraylist Java: Обнаружить дубликаты в ArrayList?
- concurrency Что такое состояние гонки?
- concurrency Что такое тупик?
- concurrency Что такое мьютекс?
- concurrency Безопасно ли получать значения из java.util.HashMap из нескольких потоков (без изменений)?
- concurrency Вы когда-нибудь использовали ключевое слово volatile в Java?
- concurrency Java 1.4 synchronization: only allow one instance of method to run (non blocking)?