Вектор синхронизируется, ArrayList не синхронизируется, но мы можем синхронизировать ArrayList Collections.synchronizedList(aList)
, таким образом, который будет работать лучше и быстрее?
Синхронизированные коллекции - пустая трата времени и опасны. Тривиальный пример того, почему они плохи, - рассмотреть два потока, выполняющих цикл одновременно в одной и той же коллекции:
int i = 0;
while (i < list.size())
{
if (testSomeCondition(list.get())) {
list.remove(i);
else
i++;
}
Наш список может быть синхронизирован (например, вектор), и этот код все равно ужасно сломается. Почему? Поскольку отдельные вызовы size (), get (), remove () синхронизированы, но один поток все еще может удалять элементы из списка, в то время как другой выполняет итерацию по нему. Другими словами, у нас есть состояние гонки, и использование синхронизированных коллекций нам ничего не дало.
Чтобы исправить гонку, мы должны синхронизировать всю операцию над коллекцией или использовать блокировки параллелизма Java 5, чтобы сделать то же самое.
synchronized (list) {
int i = 0;
while (i < list.size())
{
if (testSomeCondition(list.get())) {
list.remove(i);
else
i++;
}
}
Этот блок кода теперь является потокобезопасным, поскольку только один поток может выполнять цикл за раз. И теперь нет смысла использовать синхронизированную коллекцию. Мы можем использовать ArrayList вместо Vector и сэкономить на производительности для всех этих синхронизированных вызовов.
Так что не используйте синхронизированные коллекции. Если вы обнаружите, что несколько потоков обращаются к одному и тому же списку, вам необходимо защитить операции в списке, а не отдельные вызовы.