2

我想在两个处理程序线程对象之间同步 Android 中的对象模型。一个对象是“可观察的”,第二个是观察者。它们都无限地在自己的线程中工作。观察者通过“registerListener”方法注册到 observable 并传递自己的引用和自己的 Handler。

并且可观察对象通过他们的回调方法(通过处理程序)传递给他们的观察者对象模型。对象模型被声明为“final”,因为我不会创建无限新的对象,而是用新值(getter 和 setter)更新其字段。

我不想将对象引用传递给观察者(对象是可变的)并且我不想使用“同步”关键字,因为我不想阻塞线程。

所以我的想法是在“可观察”对象中创建两个相同的对象模型。它们都将是“最终的”,其中一个将由“可观察”对象使用并在其线程中更改,第二个将根据观察者线程中的第一个对象进行更改。因此,对象将由观察者处理程序同步。这是个好主意吗?我希望我的描述清楚。

4

3 回答 3

1

通常,当您说“多线程”时,您是在暗示“同步”,因此您不使用synchronized关键字的愿望对我来说听起来很奇怪。现在回答你的问题...

如果我理解正确,您想在不同线程之间共享一些状态(存储在“对象模型”中),但不使用synchronized关键字。此外,您提到I do not want to pass object reference to observers (object is mutable)观察者不应修改对象状态的提示。

如果上面的描述是正确的,那么您可以将您的“对象模型”复制到“可观察线程”中并将其传递给“观察线程”中的回调。这些方面的东西(未经测试):

private void notifyListeners() {
    for (int i=0; i<mListeners.size(); i++) {
        final ObjectModel copyModel = new ObjectModel(mModel); // Assuming copy-constructor exists
        mHandlers.get(i).post(new Runnable{
            mListeners.get(i).notify(copyModel);
        });
    }
}

请注意,这种方法有一些缺点:

  1. 复制构造后,传递给您的侦听器的对象不再“跟踪”可观察对象的状态。这意味着您的听众可能正在处理过时的数据。
  2. notifyListeners您在每次调用方法时为每个侦听器复制“对象模型” 。这可能会成为主要开销(取决于模型的大小、侦听器的数量和通知的速率)
  3. 如果您希望您的听众将来能够修改模型,您将需要完全更改您的代码。

由于上述原因,我建议不要使用上述方法,除了最简单的情况。在其他情况下,我会将原始对象传递给侦听器并确保线程安全。一些可以帮助您的注意事项:

  1. 为了防止监听器修改模型,您可以使用接口隔离原则。总体思路:定义两个独立的接口——一个用于读取模型的状态,另一个用于更改此状态(例如WritableModelReadableModel)。让你的“对象模型”同时实现,然后将此模型作为ReadableModel. 这样,您将只向模型的非变异 API 公开侦听器。
  2. 由于只有一个线程可以更改模型的状态,因此您可以使用volatile成员而不是完全同步方案。这将减少对synchronized块的需求。请记住,虽然volatile关键字解决了可见性问题,但它不能解决原子性问题(即,您仍然需要使用synchronized非原子编写的模型成员)。
  3. 您可以使用 package.json 中的类,而不是自己同步非原子编写的成员java.util.concurrent.atomic
于 2015-10-12T19:43:57.533 回答
0

我认为最好的选择是使用 ThreadLocal 对象并为每个线程拥有对象模型的实例。

于 2015-10-12T18:27:04.670 回答
0

您可以尝试 EveyBus:https ://github.com/greenrobot/EventBus 使用对象创建您自己的事件。像这样EventBus.getDefault().post(new MyEventResult());

于 2015-10-11T20:04:46.363 回答