Синхронизация публикации записей журнала на сервере - PullRequest
0 голосов
/ 14 апреля 2011

У меня небольшая проблема с моим проектом.Я разрабатываю приложение для Android и хочу опубликовать свои журналы на сервере.Почти все работает нормально, но у меня возникла небольшая проблема.У меня есть ArrayList в моем классе, который обрабатывает сообщения:

private ArrayList<String> logsToPost = new ArrayList<String>();

и метод, который помещает данные в этот список, и отдельный поток, который запускается каждые 20 секунд и загружает журналы и очищает список после этого.Проблема в том, что я получаю исключение ConcurrentModificationException, если я пытаюсь записать этот список, пока поток пытается загрузить данные и очистить список.Мой код выглядит следующим образом:

Iterator<String> keyIter = logsToPost.iterator();
        while (keyIter.hasNext()) {
        String next = keyIter.next();
        String[] params = next.split(FormFactory.FUNCTION_SEP);
        HttpData hd = HttpRequest.post(LOGCAT_LOG_URL, "userId=" + sb.userId + "&pdaId=" + sb.pdaId
                + "&tag=" + params[0] + "&logContent=" + params[1]);
        logsToPost.remove(next);
        }

Я знаю, что есть synchronizedList и синхронизированные блоки, но я не могу заставить synchronizedList работать на моем дроиде.У вас есть идеи, как я могу реализовать эту процедуру регистрации?Я попытался использовать ключевое слово volatile, но все равно получаю исключение.

Ответы [ 3 ]

2 голосов
/ 14 апреля 2011

С точки зрения Java:

Ваш код всегда должен приводить к исключению, так как вы модифицируете ArrayList, используя ArrayList.remove вместо Iterator.remove, одновременно перебирая его.

Внесение этого изменения должно решить вашу проблему в большинстве случаев:

Iterator<String> keyIter = logsToPost.iterator();
while (keyIter.hasNext()) {
    String next = keyIter.next();
    //do something
    keyIter.remove();
}

Чтобы еще больше защитить вашу задачу от риска сбоя, вам следует рассмотреть возможность атомарной замены экземпляра ArrayList в начале вашей задачи ведения журнала. Таким образом, рабочий процесс будет:

ArrayList<String> logsToPost = logListReference.getAndSet(new ArrayList<String>());
for (String logEntry:logsToPost) {
    //doSomething
}
1 голос
/ 14 апреля 2011
  1. Использовать синхронизированный сбор для общего списка:

    private Vector logsToPost = new Vector ();

  2. Получите копию этой коллекции перед загрузкой данных:

ArrayList<String> logsToUpload;
synchronized(logsToPost) {
  logsToUpload = new ArrayList<String>(logsToPost);
  logsToPost.clear();
}
  1. Используйте копию коллекции в цикле отправки:

    Итератор keyIter = logsToUpload.iterator ();

1 голос
/ 14 апреля 2011

Будет ли возможным обмен списками при запуске процесса отправки. Чтобы процесс отправки всегда использовал «старый» список, а процесс записи - «новый» список.

Тогда вам нужно только синхронизировать запись в новый список и их обмен

Позвольте мне проиллюстрировать это:

public class ListHolder {

  private List newList = new List();

  public syncronized List exchangeAndGetOld() {
    List oldList = this.newList;
    this.newList = new List();
    return oldList();
  }

  public syncronized addToNewList(Object item) {
    newList.add(item);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...