Ответ 1
Да, вы можете - ваш расширенный цикл for в основном такой же, как ваш код, который явно использует итератор. Он сводится к одному и тому же коду - он просто вызывает iterator()
, а затем чередует вызовы next()
и hasNext()
.
Документация по synchronizedList утверждает, что
Обязательно, чтобы пользователь вручную выполнял синхронизацию по возвращенному списку при итерации по нему:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Несоблюдение этого совета может привести к недетерминированному поведению.
Это кажется довольно ясным, но я просто хотел подтвердить, что для каждого цикла запрещено. Например, я не могу сделать что-то вроде следующего правильно?
List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>));
...
synchronized(list){
for(MyType m : list){
foo(m);
m.doSomething();
}
}
Да, вы можете - ваш расширенный цикл for в основном такой же, как ваш код, который явно использует итератор. Он сводится к одному и тому же коду - он просто вызывает iterator()
, а затем чередует вызовы next()
и hasNext()
.
Вы можете это сделать. Цикл foreach компилирует (почти) тот же байт-код, что и цикл while. Клавиши:
Конечно, вы можете, единственная проблема, которую я вижу здесь, - это проблема производительности, если ваш метод dosomething()
или foo(m)
будет дорогостоящим для выполнения, у вас будет стоимость исполнения. Размер вашей коллекции также очень важен для учета во время цикла в синхронизированном блоке из-за того, что когда поток получает блокировку, а в синхронизированном блоке цикл в огромной коллекции заставит другие потоки ждать.
Если возможно, вы можете захотеть использовать неизменяемость, а не синхронизацию.