我有一個ArrayList
正在實例化並在後臺線程上填充(我用它來存儲Cursor
數據)。同時它可以在主線程中訪問,並通過使用foreach進行迭代。所以這顯然可能會導致拋出異常。使用foreach迭代ArrayList時的線程安全
我的問題是什麼是最好的做法,使這個類字段線程安全,而無需每次複製或使用標誌?
class SomeClass {
private final Context mContext;
private List<String> mList = null;
SomeClass(Context context) {
mContext = context;
}
public void populateList() {
new Thread(new Runnable() {
@Override
public void run() {
mList = new ArrayList<>();
Cursor cursor = mContext.getContentResolver().query(
DataProvider.CONTENT_URI, null, null, null, null);
try {
while (cursor.moveToNext()) {
mList.add(cursor.getString(cursor.getColumnIndex(DataProvider.NAME)));
}
} catch (Exception e) {
Log.e("Error", e.getMessage(), e);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}).start();
}
public boolean searchList(String query) { // Invoked on the main thread
if (mList != null) {
for (String name : mList) {
if (name.equals(query) {
return true;
}
}
}
return false;
}
}
我更喜歡'CopyOnWriteArrayList',但OP說「沒有複製」。也許他想保證「一次只有一個線程可以運行受保護的塊」。 – beatngu13
「不要複製」 - 要求是毫無意義的。當然,CopyOnWriteArrayList *會複製內容,但這是實現細節的一部分。唯一的選擇是擁有一個同步塊,在地圖本身上進行同步,這在使用'null'初始化時很容易出錯。使用'Vector'不會阻止'ConcurrentModificationException',因爲它與併發無關(在迭代器嘗試繼續時會拋出,但在創建迭代器後列表已被修改) –
謝謝說明。我猜'CopyOnWriteArrayList'對我來說更好(因爲我在UI線程上訪問這個字段)。 – Nikolai