Синхронизировать сериализацию объектов (Android) - PullRequest
1 голос
/ 02 марта 2012

tl; dr: У меня есть два потока, один из них распознает объект, а другой пытается прочитать объект.Как избежать коллизий, т. Е. Синхронизировать доступ к файлу?

Дополнительная информация: У меня есть служба, которая использует AsyncTask для получения данных, а затем сериализует объект:

  @Override
  protected Boolean doInBackground(Void... params) {
      FeedItem currentItem = mParser.parseFeed();
      Util.saveItem(UpdateService.this, currentItem);       
  }

Сериализация объекта:

public class Util {

    private static final String sFileName = "feedobject";

    public static FeedItem loadItem(Context context) {
        FeedItem result = null;
        try {
            FileInputStream fis = context.openFileInput(sFileName);
            ObjectInputStream is = new ObjectInputStream(fis);
            result = (FeedItem) is.readObject();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void saveItem(Context context, FeedItem item) {
        FileOutputStream fos;
        try {
            fos = context.openFileOutput(sFileName, Context.MODE_PRIVATE);
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(item);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Я также пытаюсь прочитать объект из Activity, т.е. из потока пользовательского интерфейса.

mTextView.setText(Html.fromHtml(Util.loadItem(this).message));

1 Ответ

0 голосов
/ 02 марта 2012

Если вы можете переименовать файлы под Android, то вы можете записать объект во временный файл "feedobject.t", а затем переименовать его в "feedobject", который должен быть атомарным.

private static final String sFileName = "feedobject";
private static final String tempFileName = "feedobject.t";
...

File tempFile = new File(tempFileName);
... // write the file
tempFile.renameTo(new File(sFileName));

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

Вы можете просто синхронизировать методы saveItem и loadItem, что блокирует класс:

public static synchronized FeedItem loadItem(Context context) {
    ...

public static synchronized void saveItem(Context context, FeedItem item) {
    ...

Лучше было бы создать объект блокировки и заблокировать его:

private static final Object itemLock = new Object();

Затем в методах loadItem и saveItem вы бы заблокировали этот объект:

public static FeedItem loadItem(Context context) {
    synchronized (itemLock) {
        // do the reading...
    }

Надеюсь, это поможет.

...