Кажется, все утверждают, что вы используете List
для хранения очереди заданий, но я не вижу этого в вашем вопросе.Но если это так, или если манипуляции со списком не зависят друг от друга - то есть, если вы просто добавляете или удаляете из списка, а не сканируете список и удаляете некоторые элементы из середины как частьзадание - тогда вам следует рассмотреть возможность использования BlockingQueue
или QueueDeque
вместо List
и простого использования пакета java.util.concurrent
.Эти типы не требуют внешнего управления блокировками.
Если вам требуется всесторонне List
, к которому одновременно обращается каждая работа, когда чтение и запись в список не являются независимыми, я бы инкапсулировал частьобработка, которая выполняет эту манипуляцию в одиночном коде и использует эксклюзивную блокировку, чтобы каждый поток использовал список.Например, если ваш список содержит какую-либо статистическую статистику, являющуюся только частью выполнения процесса, тогда моя работа должна быть одним классом, а статистическая статистика с одним элементом - отдельной.
class AggregateStatistics {
private static final AggregateStatistics aggregateStatistics =
new AggregateStatistics();
public static AggregateStatistics getAggregateStatistics () {
return aggregateStatistics;
}
private List list = new ArrayList ();
private Lock lock = new ReentrantLock();
public void updateAggregates (...) {
lock.lock();
try {
/* Mutation of the list */
}
finally {
lock.unlock();
}
}
}
Затем попросите вашу задачу войти в эту часть задания, получив доступ к одноэлементному вызову и вызвав для него метод, который управляется с помощью блокировки.
Никогда не передает коллекцию, которая в параллельную средутолько вызовет у вас проблемы.Вы всегда можете обойти неизменную «обертку», хотя, если она действительно подходит, используя java.util.Collections.unmodifiableList(List)
и аналогичные методы.