個人總結,若有問題,希望大家不吝指教,在此感謝。
項目中遇到一個ConcurrentModificationException異常,這種異常比較蛋疼,一般兩個線程同時訪問一個資源造成的,一個再改,一個再做別的,然後就不同步了。
Log數據中只給出一個點,不方便查詢另一個問題點。這類必須解決的就是兩個線程對同一個資源(我們這是一個HashMap)同步的問題,一個方式就是加鎖解決,這是一個總方針。但是加鎖如果加不好,就會造成UIthread的線程因爲在鎖那裏等的時間比較長而造成ANR,當然這種情況不常見,因爲你的超過5秒才能ANR,但是是有這個可能的,我們遇到了……
然後就是思考了兩個方案,一個是做一個高優先級的線程(參考android線程優先級就能知道哪個合適,有倆都可以)來對UIthread裏面對資源的訪問提出來,這樣不會ANR,但是項目大,地方多,這麼幹結構都得變,還有就是那種特別需要及時相應的地方(UI界面上的滑動動畫啥的),擔心這麼做會有一定的延時。然後就放棄了,改動貌似有點大。
第二個方案就是做備份了,那備份給UIthread去使用。何時做、咋做備份又是個問題。然後就各種參考,這裏不得不說,Android源碼還是很碉堡的,最起碼比我見過的一些大一點的項目代碼要好。
給出一段代碼,下面一段代碼是桌面源碼launcherModle裏面的一段代碼。
代碼中sBgWorkspaceItems、sBgAppWidgets就是workerThread和UIthread都可能訪問到的資源。在這段中做了兩個備份,Runnable中用的備份。加了一個鎖,只鎖一小段代碼,基本不會造成ANR。這就是一個原則,如果是workerThread和UIthread都可能訪問到的資源,那麼對這類資源加鎖儘量短。看了代碼大家應該就知道怎麼搞好了。
/** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
void unbindWorkspaceItemsOnMainThread() {
// Ensure that we don't use the same workspace items data structure on the main thread
// by making a copy of workspace items first.
final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();
final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();
synchronized (sBgLock) {
tmpWorkspaceItems.addAll(sBgWorkspaceItems);
tmpAppWidgets.addAll(sBgAppWidgets);
}
Runnable r = new Runnable() {
@Override
public void run() {
for (ItemInfo item : tmpWorkspaceItems) {
item.unbind();
}
for (ItemInfo item : tmpAppWidgets) {
item.unbind();
}
}
};
runOnMainThread(r);
}