В текущей форме он не является потокобезопасным: метод useComponents
может выполняться одним потоком. В то же время другой поток может вызвать add
и, таким образом, модифицировать коллекцию во время ее повторения. (Эта модификация может произойти между двумя звонками до c.use()
, поэтому тот факт, что метод use()
является потокобезопасным, не поможет вам здесь).
Строго говоря, это даже не ограничивается многопоточности: Если c.use()
внутренне называется test.add(someOtherComponent)
(! Даже если это было сделано в том же потоке) это было бы бросить ConcurrentModificiationException
, потому что опять же, коллекция была изменена в то же время перевернулся.
безопасность резьбы (без Agains безопасности одновременных модификаций) может быть достигнута путем простого обертывания итерации в synchronized
блока:
public void useComponents()
{
synchronized (myContainer)
{
for(Component c : myContainer)
c.use(); // method thread-safe
}
}
Тем не менее, это все еще оставить возможность ConcurrentModificationException
. Скорее всего, вызов c.use()
не будет (и не должен) модифицировать коллекцию, в которой находится компонент (в противном случае можно было бы спросить дизайн в целом).
Если вы хотите, чтобы позволить c.use()
вызов изменить коллекцию, вы могли бы заменить коллекцию с CopyOnWriteArrayList
:
private final List<Component> myContainer =
new CopyOnWriteArrayList<Component>();
, а затем вы можете даже удалить synchroniziation полностью. Но вы должны знать о последствиях: содержимое списка будет скопировано во время каждой модификации (отсюда и название ...). Обычно это используется в случаях, когда у вас есть небольшая коллекция, которая часто повторяется, но которая редко изменяется. (Слушатели во всех формах являются классическим примером здесь).
Предоставьте необходимый код для повторения вашего сценария. В текущем описании код все равно может быть небезопасным. –
Allawys поток небезопасный? @LuiggiMendoza – kaoziun
'useComponents' является небезопасным. Любой другой поток может добавить новый «Компонент», пока вы пересекаете внутренние элементы 'myContainer'. –