Обнаружение параллельных модификаций?

В SHORT SOLUTION

Это происходит только при отправке сообщений через консоль firebase, а не в apis

Проблема

Переключение с старого gcm на новый FirebaseMessagingService я подумал, что было бы хорошо протестировать, поэтому я создал сообщения, используя консоль firebase, и обнаружил, что когда приложение является фоном, мое пользовательское уведомление не работает, а Firebase onMessageReceived не вызывается, когда приложение в фоновом режиме

Решение

Я попытался создать сообщения из api, и только тогда я понял, что Firebase onMessageReceived не вызывается, когда приложение в фоновом режиме возникает только при создании сообщений из Firebase Console, а не при отправке из API

9
задан Durandal 24 February 2014 в 04:17
поделиться

12 ответов

Ваш исходный вопрос, кажется, просит итератор, который видит живые обновления базового набора, оставаясь ориентированным на многопотоковое исполнение. Это - невероятно дорогая проблема для решения в общем случае, который является, почему ни один из стандартных классов набора не делает это.

Существует много способов достигнуть частичных решений проблемы, и в Вашем приложении, один из тех может быть достаточным.

Jason дает особенный метод достигнуть потокобезопасности и постараться не бросать ConcurrentModificationException, но только за счет живучести.

Javamann упоминает два определенных класса в java.util.concurrent пакет, которые решают ту же проблему свободным от блокировок способом, где масштабируемость очень важна. Они только поставлялись с Java 5, но были различные проекты, которые бэкпортируют функциональность пакета в более ранние версии Java, включая этого, хотя у них не будет такой хорошей производительности в ранее JREs.

Если Вы уже пользуетесь некоторыми библиотеками Apache Commons, то, поскольку jacekfoo указывает, апачская платформа наборов содержит некоторые полезные классы.

Вы могли бы также рассмотреть рассмотрение платформы наборов Google.

4
ответ дан 4 December 2019 в 10:06
поделиться

В зависимости от Вашей частоты обновления одним из моего избранного является CopyOnWriteArrayList или CopyOnWriteArraySet. Они создают новый список/набор на обновлениях для предотвращения параллельного исключения модификации.

6
ответ дан 4 December 2019 в 10:06
поделиться

Проверьте java.util.concurrent для версий стандартных классов Наборов, которые спроектированы для обработки параллелизма лучше.

3
ответ дан 4 December 2019 в 10:06
поделиться

Вы могли попытаться использовать копирование обороны так, чтобы модификации одной List не влияйте на других.

1
ответ дан 4 December 2019 в 10:06
поделиться

Обычно Вы получаете ConcurrentModificationException, при попытке удалить элемент из списка, пока он выполняется с помощью итераций через.

Самый легкий способ протестировать это:

List<Blah> list = new ArrayList<Blah>();
for (Blah blah : list) {
     list.remove(blah); // will throw the exception
}

Я не уверен, как Вы обошли бы его. Вам, вероятно, придется реализовать Ваш собственный ориентированный на многопотоковое исполнение список, или Вы могли создать копии исходного списка для записи и иметь синхронизируемый класс, который пишет в список.

2
ответ дан 4 December 2019 в 10:06
поделиться

Да необходимо синхронизировать доступ к объектам наборов.

С другой стороны, можно использовать синхронизируемые обертки вокруг любого существующего объекта. См. Collections.synchronizedCollection (). Например:

List<String> safeList = Collections.synchronizedList( originalList );

Однако весь код должен использовать безопасную версию, и несмотря на это итерация, в то время как другой поток изменяет, приведет к проблемам.

Для решения итеративной проблемы скопируйте список сначала. Пример:

for ( String el : safeList.clone() )
{ ... }

Для более оптимизированных, ориентированных на многопотоковое исполнение наборов также посмотрите на java.util.concurrent.

3
ответ дан 4 December 2019 в 10:06
поделиться

Обертывание доступов к набору в синхронизируемом блоке является корректным способом сделать это. Стандартная практика программирования диктует какое-то использование блокировки механизма (семафор, взаимное исключение, и т.д.) при контакте с состоянием, которое совместно используется через несколько потоков.

В зависимости от Вашего варианта использования однако можно обычно делать некоторую оптимизацию, чтобы только привязать определенные случаи. Например, если у Вас есть набор, который часто читается, но редко пишется, затем можно позволить параллельные чтения, но осуществить блокировку каждый раз, когда запись происходит. Параллельные чтения только вызывают конфликты, если набор находится в процессе того, чтобы быть измененным.

1
ответ дан 4 December 2019 в 10:06
поделиться

ConcurrentModificationException является максимальными усилиями, потому что то, что Вы спрашиваете, является тяжелой проблемой. Нет никакого хорошего способа сделать это надежно, не жертвуя производительностью помимо доказательства, что Ваши схемы доступа одновременно не изменяют список.

Синхронизация, вероятно, предотвратила бы параллельные модификации, и это может быть тем, к чему Вы обращаетесь в конце, но это может закончить тем, что было дорогостоящим. Лучшая вещь сделать состоит в том, чтобы, вероятно, сесть и думать некоторое время о Вашем алгоритме. Если Вы не можете предложить свободное от блокировок решение, затем обратиться к синхронизации.

1
ответ дан 4 December 2019 в 10:06
поделиться

Посмотрите реализацию. Это в основном хранит интервал:

transient volatile int modCount;

и это увеличено, когда существует 'структурная модификация' (как, удаляют). Если итератор обнаруживает, что modCount изменился, он выдает Параллельное исключение модификации.

Синхронизация (через Collections.synchronizedXXX) не будет делать хорошее, так как это не гарантирует безопасности итератора, это только синхронизирует записи и чтения через помещенный, получите, установите...

См. java.util.concurennt и апачскую платформу наборов (это имеет некоторые классы, которые оптимизированы, действительно работают правильно в параллельной среде, когда существует больше чтений (которые не синхронизируются), чем записи - видят FastHashMap.

1
ответ дан 4 December 2019 в 10:06
поделиться

Collections.synchronizedList () представит список, номинально ориентированный на многопотоковое исполнение, и java.util.concurrent имеет более мощные функции.

-1
ответ дан 4 December 2019 в 10:06
поделиться

Вы также можете синхронизировать по итерациям по списку.

List<String> safeList = Collections.synchronizedList( originalList );

public void doSomething() {
   synchronized(safeList){
     for(String s : safeList){
           System.out.println(s);

     }
   }

}

Это заблокирует список при синхронизации и заблокирует все потоки, которые пытаются получить доступ к списку во время его редактирования или итерации по нему. Недостатком является то, что вы создаете узкое место.

Это экономит часть памяти по методу .clone () и может быть быстрее в зависимости от того, что вы делаете в итерации ...

1
ответ дан 4 December 2019 в 10:06
поделиться

Это избавится от Вашего параллельного исключения модификации. Я не буду говорить с эффективностью однако ;)

List<Blah> list = fillMyList();
List<Blah> temp = new ArrayList<Blah>();
for (Blah blah : list) {
     //list.remove(blah);  would throw the exception
     temp.add(blah);
}
list.removeAll(temp);
-1
ответ дан 4 December 2019 в 10:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: