0

我有一个关于 CommonsWare 5.9 事件总线示例的线程安全问题/问题。

model ArrayList在我看来,从多个线程访问的方式存在问题。如果这可行,我将不胜感激理解原因。

此代码执行model.

private static final String[] items= { "lorem", "ipsum", "dolor",
  "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
  "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
  "vel", "erat", "placerat", "ante", "porttitor", "sodales",
  "pellentesque", "augue", "purus" };
private ArrayList<String> model=new ArrayList<String>();
private boolean isStarted=false;

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  setRetainInstance(true);

  if (!isStarted) {
    isStarted=true;
    new LoadWordsThread().start();
  }
}

public ArrayList<String> getModel() {
  return(model);
}

class LoadWordsThread extends Thread {
  @Override
  public void run() {
    for (String item : items) {
      if (!isInterrupted()) {
        model.add(item);
        EventBus.getDefault().post(new WordReadyEvent());
        SystemClock.sleep(400);
      }
    }
  }
}

它每 400 毫秒唤醒一次,并在model. 的model使用有点复杂,因为我没有方便发布的代码。它在某个ArrayAdapter. 模型的消耗是通过调用来触发的ArrayAdapter.notifyDataSetChanged()

我遇到的问题/问题model是写在一个线程(不是 Android UI 线程)中,但消耗发生在 UI 线程上。的所有元素model ArrayList都是不可变的,这有帮助,但对我来说似乎仍然不正确。

如果此代码实际上是正确的,我想了解原因。谢谢,李。

更新:

我认为我的问题不在于事件总线部分。我想我明白了。这几乎是我在该模型中的一个 java 问题,它被写入一个线程(工作线程,上面的代码),而理论上它可以同时从另一个线程(UI 线程)中读取。在我看来,模型上需要有某种并发访问控制。同步块或并发ArrayList。但是模型的最终消费者是我在我的应用程序中无法控制的代码,它在ArrayAdapter某个地方。我无法为其添加同步。一旦ArrayAdapter使用模型初始化,则ArrayAdapter拥有它并将从 UI 线程访问它。我不确定非 UI 线程是否可以通过这种方式修改模型。

4

1 回答 1

1

你是对的——这个示例应用程序有缺陷。我试图积极地最小化代码,但我走得太远了。

需要进行的两个更改是:

  1. AsyncDemoFragment应该使用模型的副本ArrayList<String>,从当时的模型初始化,而不是实际上模型

  2. 除了触发之外,我应该提供 in 中的单词WordReadyEvent,以允许AsyncDemoFragment更新其模型副本notifyDataSetChanged()

这将允许后台线程更新和维护后台线程上的模型主副本,让 UI 线程根据需要了解更改,并允许 UI 线程检索该模型的副本以供 UI 使用。

在其他情况下,拥有一个共享的、同步的模型并不是不可能的。在这种情况下,这是不切实际的,没有 kcoppock 建议创建一个定制的适配器类,这就像在这种情况下用别克拍苍蝇一样。

我会在下一次图书更新时解决这个问题。

顺便说一句,我问你是否阅读过这一章的原因仅仅是因为有些人仅仅根据检查 repo 提出问题,我想知道你是否阅读过样本随附的材料。我的评论可能会被解释为暗示如果您阅读该章,您将获得您的问题的答案,我绝对不是那个意思。如果我糟糕的措辞给您带来任何问题,我深表歉意。

感谢您指出问题!

于 2014-07-15T22:49:44.837 回答