- Java util concurrentmodificationexception android
- Избавляемся от ConcurrentModificationException
- Concurrent Modification Exception Class
- Definition
- Remarks
- Constructors
- Fields
- Properties
- Methods
- Explicit Interface Implementations
- Extension Methods
- Java util concurrentmodificationexception android
- Как бороться с ConcurrentModificationException в Java?
- ConcurrentModificationException в одной теме
- Использование Classical для цикла и ArrayList.remove (index)
- Использование Iterator, но метод удаления ArrayList
- Правильный способ удаления элемента — использование метода удаления Итератора.
Java util concurrentmodificationexception android
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
Источник
Избавляемся от ConcurrentModificationException
Как известно, ConcurrentModificationException к многопоточности никакого отношения не имеет. Возникает эта гадость, когда мы пытаемся модифицировать коллекцию во время итерирования по ней. Как обычно, это имеет исторические корни: коллекции и итераторы появились в Java 1.2, в те времена избежать явного использования итератора при обходе коллекции было никак нельзя, так что предложение менять коллекцию посредством методов итератора не выглядело совсем ужасным:
Не, всё же выглядело. Но никаких других вариантов не было. Позже в пятой джаве появляется цикл foreach, и использование итераторов становится преимущественно неявным:
«Ишь чего захотели! Юзайте явные итераторы, дорогие кастомеры, и не выделывайтесь» — наверное что-то такое думали разработчики джава платформы работая над пятеркой.
В шестой джаве появляется пакет конкаренси. Теперь можно cделать так:
И получить set который не кидается ConcurrentModificationException-ами. Но опять же счастье не совсем полное:
- Oбычно многопоточность нам вовсе не нужна
- Не подерживаются null ни в качестве элементов, ни ключей, ни значений. Да и ладно, честно сказать.
- Порядок элементов не определён и может меняться — вот это гораздо хуже. Т.е. если мы бежим по элементам и ведём некий подсчёт с потерей точности, то нас могут поджидать неприятные сюрпризы и разные результаты на одних и тех же наборах данных, что, скажем, не всегда хорошо. Так же бывают задачи, где желательно сохранить именно изначальный порядок данных. Ну и вот такие штуки тоже имеют место быть:
Вывод |
Поэтому сейчас мы сделаем свою собственную коллекцию с чётким порядком. И так, что мы хотим получить:
- В рамках одного треда можно добавлять и удалять элементы в любой момент без всяких эксепшенов. И конечно же за константное время.
- Можно хранить null-ы, если вдруг хочется.
- Элементы обходятся в том порядке в котором были добавлены.
Всё это с легкостью достигается с помощью слегка доработанного двунаправленного списка:
- Удаляя элемент мы не будем обнулять ссылку на следующий, т. е. eсли итератор стоит на данном элементе, то он сможет пройти дальше.
- В конце списка поместим фэйковый элемент, который превращается в настоящий когда в список что-нибудь добавляют. Т.е. даже добравшись до конца списка итератор не упирается в null и может продолжить работу если в коллекции появляется новый элемент. Далее в коде этот фейковый элемент называется placeholder.
Посмотрим на картинку.
- В начале у нас есть элементы A, B, C, D.
- Затем элементы C и D удаляются.
- Добавляется новый элемент E.
Можно заметить, что если на момент удалений у нас был итератор указывавший на элемент С, то двигаясь дальше по ссылкам он доберется до вновь добавленного элемента E. Если же никакого итератора не было, то ничто не мешает сборщику мусора освободить память от удаленных элементов.
Ну и для константного времени доступа нам, очевидно, нужен хэшмап:
Теперь можно делать так:
Понятно, что аналогично можно сконструировать и LinkedMap. Вот в общем-то и всё, ещё один велосипед готов. Почему подобным образом не доработали библиотечные LinkedHashMap и LinkedHashSet? Кто знает, возможно чтобы джависты завидовали джаваскриптистам.
Источник
Concurrent Modification Exception Class
Definition
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
Remarks
Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Constructors
Constructs a ConcurrentModificationException with no detail message.
A constructor used when creating managed representations of JNI objects; called by the runtime.
Constructs a ConcurrentModificationException with no detail message.
Constructs a ConcurrentModificationException with no detail message.
Constructs a ConcurrentModificationException with no detail message.
Fields
Properties
Returns the cause of this throwable or null if the cause is nonexistent or unknown.
(Inherited from Throwable)
The handle to the underlying Android instance.
(Inherited from Throwable)
Creates a localized description of this throwable.
(Inherited from Throwable)
Returns the detail message string of this throwable.
(Inherited from Throwable)
This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.
This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.
Methods
Appends the specified exception to the exceptions that were suppressed in order to deliver this exception.
(Inherited from Throwable)
Fills in the execution stack trace.
(Inherited from Throwable)
Provides programmatic access to the stack trace information printed by #printStackTrace() .
(Inherited from Throwable)
Returns an array containing all of the exceptions that were suppressed, typically by the try -with-resources statement, in order to deliver this exception.
(Inherited from Throwable)
Initializes the cause of this throwable to the specified value.
(Inherited from Throwable)
Prints this throwable and its backtrace to the standard error stream.
(Inherited from Throwable)
Prints this throwable and its backtrace to the standard error stream.
(Inherited from Throwable)
Prints this throwable and its backtrace to the standard error stream.
(Inherited from Throwable)
Sets the Handle property.
(Inherited from Throwable)
Sets the stack trace elements that will be returned by #getStackTrace() and printed by #printStackTrace() and related methods.
(Inherited from Throwable)
Explicit Interface Implementations
IJavaPeerable.Disposed() | (Inherited from Throwable) |
IJavaPeerable.DisposeUnlessReferenced() | (Inherited from Throwable) |
IJavaPeerable.Finalized() | (Inherited from Throwable) |
IJavaPeerable.JniManagedPeerState | (Inherited from Throwable) |
IJavaPeerable.SetJniIdentityHashCode(Int32) | (Inherited from Throwable) |
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) | (Inherited from Throwable) |
IJavaPeerable.SetPeerReference(JniObjectReference) | (Inherited from Throwable) |
Extension Methods
Performs an Android runtime-checked type conversion.
Источник
Java util concurrentmodificationexception android
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
Источник
Как бороться с ConcurrentModificationException в Java?
Одной из распространенных проблем при удалении элементов из ArrayList в Java является исключение ConcurrentModificationException. Если вы используете классический цикл for с индексом или расширенный цикл for и пытаетесь удалить элемент из ArrayList с помощью метода remove() , вы получите oncurrentModificationException C oncurrentModificationException но если вы используете метод удаления Iterator или метод ListIterator’s
метод remove() , тогда вы не получите эту ошибку и не сможете удалить элемент. Это неписанное правило в Java, что при циклическом просмотре списка не следует add() элементы add() или remove() пока коллекция не поддерживает отказоустойчивый итератор, например, CopyOnWriteArrayList , которые работают с копией списка, а не с оригинальным списком.
Основная проблема с этой ошибкой состоит в том, что это смущает разработчика, что список изменяется несколькими потоками, и именно поэтому Java выдает эту ошибку, это не так. Большую часть времени
ConcurrentModificationException приходит даже без нескольких потоков, изменяющих список.
Это неправильно, не обманывайтесь этим. хотя кажется естественным думать, что, возможно, какой-то другой поток пытается изменить коллекцию одновременно, он обычно нарушает правило Java.
В этой статье я объясню эту ошибку, и мы приведем множество примеров кода, чтобы воспроизвести этот код даже в одном потоке, и узнаем, как избежать ошибки одновременного изменения при изменении ArrayList в Java.
Кстати, если вы не знакомы с коллекционными классами, например, с самим ArrayList, то вам следует присоединиться к онлайн-курсу, например
Основы Java: научитесь правильно писать код на Udemy — это хорошее место для начала.
ConcurrentModificationException в одной теме
Это первый пример воспроизведения исключения одновременной модификации в Java. В этой программе мы перебираем ArrayList, используя расширенный цикл foreach, и удаляем селективные элементы, например, элемент, который соответствует определенному условию, используя метод удаления ArrayList.
Например, в приведенном ниже коде мы сначала добавили пару хороших книг по программированию, например, « Программирование жемчужин» , « Чистый код» , « Код завершен», в ArrayList, а затем удалили любой элемент, в заголовке которого есть «Код».
Вы можете видеть, что эта ошибка возникает, хотя у нас только один поток, основной поток, который работает с ArrayList. Ошибка ConcurrentModification происходит потому, что мы не используем Iterator, а просто вызываем listOfBooks.remove() .
В этом коде я использовал Java 1.5, улучшенную для цикла, вы должны знать, как расширен для цикла работает в Java.
Разница между циклом for и расширенным циклом for заключается в том, что позднее внутренне использует Iterator для просмотра всех элементов коллекции. Для более глубокого обсуждения, см. Здесь
Использование Classical для цикла и ArrayList.remove (index)
Вот еще один интересный пример кода удаления элементов из ArrayList. Удивительно, но этот код не вызовет исключение ConcurrentModificationException при первом его запуске? ты знаешь почему?
Что ж, попробуйте, прежде чем посмотреть объяснение после кода. Это действительно мелкие детали о языке программирования Java и платформе Collection, которые сделают вас хорошим разработчиком, а также помогут вам получить сертификат Java, если вы к нему готовитесь.
Этот код не генерирует ConcurrentModificationException потому что здесь мы не используем Iterator, а просто используем традиционный цикл for.
Это итератор, который ConcurrentModificationException исключение ConcurrentModificationException , а не метод удаления ArrayList , поэтому вы не увидите эту ошибку в приведенном ниже коде.
Если вы посмотрите на код для ArrayList.java , вы заметите, что есть вложенный класс, который реализовал интерфейс Iterator, и его метод next () вызывает функцию checkForComodification() которая фактически проверяет, изменился ли ArrayList во время итерации или нет, если modCount не делает этого. не совпадает с expectedModCount то он вызывает ConcurrentModificationException .
Этот тип вопросов также очень популярен в Oracle Java Certification, например, OCAJP ( 1z0-808 ) и OCPJP ( 1Z0-809 ), поэтому, если вы готовитесь к этим экзаменам, вы должны знать ответ.
Вот полный фрагмент кода из класса ArrayList.java для вашей быстрой ссылки:
Использование Iterator, но метод удаления ArrayList
Теперь давайте посмотрим на другой пример кода, где Java-программист думает, что он все сделал правильно, но все еще получает исключение одновременной модификации. Можете ли вы определить ошибку? Это действительно часто встречается, и я много раз видел такой код на форумах Java, в StackOverflow и в группах Java на Facebook, где они просили решить проблему.
Реальная проблема с этим кодом состоит в том, что, хотя код использует Iterator для ArrayList , он на самом деле не использует метод Iterator.remove() для удаления элемента. Он просто использует Iterator для получения следующего элемента, но вызывает метод ArrayList.remove () для удаления элемента.
Я знаю, это выглядит легко, когда вы знаете причину, но в реальном времени программисту часто требуется даже часы, чтобы понять, что не так. Так что просто остерегайтесь этого.
Кстати, если вы изучаете Java, я предлагаю присоединиться к Complete Java Masterclass, чтобы лучше изучить Java и избежать таких распространенных ошибок.
Правильный способ удаления элемента — использование метода удаления Итератора.
Наконец, вот правильный способ удалить элемент из ArrayList во время итерации. В этом примере мы использовали Iterator как для итерации, так и для удаления элемента. Код в порядке, но имеет серьезные ограничения, вы можете использовать этот код только для удаления текущего элемента. Вы не можете удалить любой произвольный элемент из ArrayList в Java.
Такое же поведение применимо и к ListIterator . Я имею в виду, вы можете заменить Iterator на ListIterator и код будет работать нормально. ListIterator также позволяет вам перемещаться в обоих направлениях, то есть вперед и назад.
Это все о том, как избежать ConcurrentModificationException при удалении элементов из ArrayList во время итерации . Вы можете использовать ту же технику, чтобы избежать исключения ConcurrentModificationException при удалении элементов из любых других классов коллекций, которые имеют итератор без сбоев, например LinkedList. Кстати, если вы новичок в программировании на Java, то присоединение к хорошему, всеобъемлющему курсу, подобному основам Java: научитесь правильно кодировать на Udemy, поможет вам лучше и быстрее освоить Java.
Другие руководства по устранению неполадок Java, которые могут вам понравиться
Как решить ArrayIndexOutOfBoundsException в Java? ( руководство )
Как решить NullPointerException в Java? (руководство)
Как устранить ошибку «Система не может найти указанный путь»? ( решение )
Как решить NoClassDefFoundError при запуске программы Java из командной строки? ( решение )
Как устранить ошибку «Не найдена JVM, установите 64-битный JDK» в Android Studio? ( решение )
Как бороться с ошибкой SQLException «Не найден подходящий драйвер» в JDBC и MySQL? ( руководство )
Как решить NumberFormatException в Java? ( руководство )
Как решить Minecraft — java.lang.UnsatisfiedLinkError: lwjgl64.dll: доступ запрещен? ( решение )
Как исправить java.lang.ArrayIndexOutOfBoundsException: 1 в Java? ( решение )
Как исправить java.net.SocketException: программное обеспечение вызвало прерывание соединения: сбой recv ( исправить )
Спасибо за чтение этого урока. Если вам нравится этот урок, поделитесь им с друзьями и коллегами. Если у вас есть какие-либо вопросы или предложения, пожалуйста, оставьте комментарий.
Посмотрите оригинальную статью здесь: Как бороться с ConcurrentModificationException в Java? Осторожно, удаляя элементы из ArrayList в цикле |
Мнения, высказанные участниками Java Code Geeks, являются их собственными.
Источник