Android中workerthread與UIthread同時訪問同一資源造成ConcurrentModificationException解決參考

    個人總結,若有問題,希望大家不吝指教,在此感謝。

項目中遇到一個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);
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章