Этот вопрос довольно старый (извините, я немного опоздал ..), но я все еще хочу добавить свой ответ.
Я бы выбрал второй вариант (например, клонировать коллекцию перед вызовом итератора ()), но с большим поворотом.
Предполагается, что вы хотите выполнить итерацию с помощью итератора, вам не нужно копировать коллекцию перед вызовом .iterator () и что-то вроде отрицания (я использую термин "отрицание") идеи шаблона итератора, но мог написать "ThreadSafeIterator".
Это будет работать в той же предпосылке, копируя Коллекцию, но не давая знать итеративному классу, что вы сделали именно это. Такой итератор может выглядеть так:
class ThreadSafeIterator<T> implements Iterator<T> {
private final Queue<T> clients;
private T currentElement;
private final Collection<T> source;
AsynchronousIterator(final Collection<T> collection) {
clients = new LinkedList<>(collection);
this.source = collection;
}
@Override
public boolean hasNext() {
return clients.peek() != null;
}
@Override
public T next() {
currentElement = clients.poll();
return currentElement;
}
@Override
public void remove() {
synchronized(source) {
source.remove(currentElement);
}
}
}
Используя этот шаг, вы можете использовать класс Semaphore
для обеспечения безопасности потоков или чего-то еще. Но возьмите метод удаления с зерном соли.
Дело в том, что при использовании такого Итератора никто, ни итеративный, ни итеративный Класс (это реальное слово) не должен беспокоиться о безопасности потоков.