我有一个关于 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 线程是否可以通过这种方式修改模型。