что использовать в многопоточной среде; Vector или ArrayList - PullRequest
3 голосов
/ 23 августа 2010

У меня такая ситуация:

веб-приложению с одновременными запросами cca 200 (потоками) необходимо записать что-то в локальную файловую систему.У меня есть один класс, которому все потоки выполняют свои вызовы, и этот класс внутренне хранит сообщения в одном массиве (Vector или ArrayList), который затем, в свою очередь, будет записан в файловую систему.

Идея состоит в том, чтобы вернуться из вызова потокаКАК МОЖНО СКОРЕЕ, чтобы поток мог выполнять свою работу как можно быстрее, какой поток хотел записать, может быть записан в файловую систему позже, это не так важно.

Итак, этот класс, в свою очередь, удаляет первый элемент из этого списка и записываетэто в файловой системе, в то время как в реальном времени есть 10 или 20 потоков, которые добавляют новые журналы в конце этого списка.

Я хотел бы использовать ArrayList, поскольку он не синхронизирован и, следовательно, вызовы потока будут длиться меньше, вопрос:

Рискую ли я тупиковые блокировки / потеря данных?Лучше ли использовать Vector, так как он безопасен для потоков?Это медленнее использовать вектор?

Ответы [ 4 ]

16 голосов
/ 23 августа 2010

На самом деле и ArrayList, и Vector являются очень плохим выбором здесь, не из-за синхронизации (которая вам определенно понадобится), а потому, что удаление первого элемента - это O (n).

Идеальная структура данных для вашей цели - ConcurrentLinkedQueue: она обеспечивает как безопасность потоков (без синхронизации), так и добавление и удаление O (1).

2 голосов
/ 23 августа 2010

Вы ограничены конкретной (старой) версией Java?Не рекомендуется использовать java.util.concurrent.LinkedBlockingQueue для подобных вещей.Это действительно стоит посмотреть на пакет java.util.concurrent. * При работе с параллелизмом.

1 голос
/ 23 августа 2010

Вектор хуже бесполезного. Не используйте его даже при использовании многопоточности. Тривиальный пример того, почему это плохо, состоит в том, чтобы рассматривать два потока одновременно, повторяя и удаляя элементы в списке одновременно. Методы size (), get (), remove () могут быть синхронизированы, но цикл итерации не является атомарным, поэтому - kaboom. Один поток должен попытаться удалить что-то, чего нет, или пропустить элементы, потому что size () изменяется.

Вместо этого используйте блоки synchronized (), где вы ожидаете, что два потока получат доступ к одним и тем же данным.

private ArrayList myList;

void removeElement(Object e)
{
  synchronized (myList) {
    myList.remove(e);
  }
}

Java 5 предоставляет явные объекты блокировки, которые обеспечивают более детальное управление, например, возможность попытки тайм-аута, если ресурс не доступен в некоторый период времени.

private final Lock lock = new ReentrantLock();
private ArrayList myList;

void removeElement(Object e) {
{
  if (!lock.tryLock(1, TimeUnit.SECONDS)) {
    // Timeout
    throw new SomeException();
  }
  try {
    myList.remove(e);
  }
  finally {
    lock.unlock();
  }
}
0 голосов
/ 23 августа 2010

На самом деле существует незначительная разница в производительности между sychronizedlist и вектором.(http://www.javacodegeeks.com/2010/08/java-best-practices-vector-arraylist.html)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...