同步对象序列化(Android)

时间:2012-03-01 21:53:43

标签: java android multithreading java-io

TL; DR: 我有两个线程,其中一个是serealize对象,另一个是尝试读取对象。如何避免冲突,即同步访问文件?

更多信息: 我有Service使用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中读取对象,即从UI线程中读取对象。

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

1 个答案:

答案 0 :(得分:0)

如果您可以在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));

如果这不起作用,那么您将被迫进行同步锁定。消费者应该锁定并等待制作人完成写作。生产者需要锁定以确保它只在消费者不读时才写。

您可以让saveItemloadItem方法同步,这会锁定该类:

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

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

最好是创建一个锁定对象并锁定它:

private static final Object itemLock = new Object();

然后在loadItemsaveItem方法中锁定该对象:

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

希望这有帮助。