2013-07-22 97 views
4

我有一個函數:fillFromDB它填充從SQLite數據庫調用listArrayList的實例。同步塊android

我也有另一種Thread這是假設清除list和重新填充它。

我在列表中遇到了一些問題,因爲有時候其他Thread清除列表,而第一個仍在填充列表,導致適配器上的IndexOutOfBoundsException

// This occurs onCreate() 
fillFromDb(list); 
downloadAndRepopulateList(list); 


private void downloadAndRepopulateList(List list) { 
    new Thread(new Runnable() { 
     @Override public void run() { 
      list.clear(); 
      // Some other clode 
     } 
    } 
} 

我知道,這個問題是因爲他們不是線程安全的,但我從來沒有使用過​​。

所以我的問題是:

如果我改變這樣的下載功能:

private void downloadAndRepopulateList(List list) { 
    new Thread(new Runnable() { 
     @Override public void run() { 

      synchronized(list) { 

       list.clear(); 
       // Some other clode 
      } 
     } 
    } 
} 

將它等待UIThread先填完上fillFromDb()名單,然後進行清除和重新填充?

如果不是,我該怎麼做?

回答

5

雖然我寧願推薦使用LinkedBlockingQueue。即

list = new LinkedBlockingQueue<SomeType>(); 
    fillFromDb(list); 
    downloadAndRepopulateList(list); 

private void downloadAndRepopulateList(List list) { 
new Thread(new Runnable() { 
    @Override public void run() { 
     list.clear(); 
     // Some other clode 
    } 
} 
} 

LinkedBlockingQueue本身將管理同步爲你和你不需要持有任何鎖等

如果你想使使用Arraylist它,你將不得不使其從兩側原子。即要訪問list,他們應該首先保持鎖對象和繼續。如果其他人持有鎖,則等待。

synchonized(list){ 
    fillFromDb(list); 
    downloadAndRepopulateList(list); 
} 


private void downloadAndRepopulateList(List list) { 
new Thread(new Runnable() { 
    @Override public void run() { 
     synhronized(list){ 
     list.clear(); 
     } 
     // Some other clode 
    } 
} 
} 
+0

所以downloadAndRepopulateList()方法被調用同步關鍵字內,並且還具有在他的身體同步關鍵字? –

+0

是的。調用'synchornized(list)'的線程持有鎖對象。在這種情況下,你的其他線程。因此它是必要的 – Jatin

1

要使其工作,您還必須在fillFromDb方法上進行同步。所以最後你會有兩個同步部分,一個同步你的列表填充,另一個同步清除列表。你也可以使用你的列表作爲互斥鎖,但我會建議你有一個單獨的對象作爲互斥鎖,它可以像我一樣Object mutex = new Object();