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 スレッドではなく) 1 つのスレッドに書き込まれますが、消費は UI スレッドで発生しています。のすべての要素model
ArrayList
が不変であるため、これは役に立ちますが、それでも私には正しくないように思えます。
このコードが実際に正しい場合、その理由を理解したいと思います。ありがとう、リー。
アップデート:
私の問題はイベントバス部分にあるとは思いません。私はそれを得ると思います。モデルが1つのスレッド(ワーカースレッド、上記のコード)で書き込まれているのに対し、理論的には別のスレッド(UIスレッド)で同時に読み取ることができるというJavaの問題です。モデルには、ある種の同時アクセス制御が必要なようです。同期ブロックまたは並行ArrayList
. しかし、モデルの最終的な消費者は、自分のアプリで制御できないコードであり、ArrayAdapter
どこかに落ちています。同期を追加できません。がArrayAdapter
モデルで初期化されると、ArrayAdapter
がそれを所有し、UI スレッドからアクセスします。非 UI スレッドがこの方法でモデルを変更できるかどうかはわかりません。