1. 程式人生 > >Android中workerthread與UIthread同時訪問同一資源造成ConcurrentModificationException解決參考

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);
    }