2011-06-29 64 views
0

我在Android中使用外部庫,該庫有一個從另一個線程訪問的對象的ArrayList。我的問題是我想從這個AarrayList中移動一些對象,而不會在另一個線程上產生空的異常。因此,我想要做的是:我有一個ArrayList ABCDEFGH,並且我想將F從其實際位置移動到第一個位置,因此ArrayList將變爲FABCDEGH。請注意,我不能使用交換,因爲每個其他對象都右移。在ArrayList線程上移動對象的最佳方式是什麼?

一個天真的實現是:

list.remove(F); 
list.add(0,F); 

但是這種實現導致其他線程,因爲其他線程是循環的,是因爲在競爭條件的線程循環通過手寫計數循環的列表中,空異常可以在刪除和添加F之間運行。由於我無法訪問外部庫,因此無法使ArrayList更安全。

有沒有更好的方法來使這種運動(從任何位置到Arraylist的任何位置)沒有比賽條件?請注意,ArrayList的大小不會被修改。

+0

你是否擁有循環和刪除/添加的代碼?或者循環運行在庫代碼中? – sudocode

+0

循環運行庫代碼 – Akira

回答

3

如果您擁有循環和交換代碼,則可以同步列表上的兩個操作。

// code for loop 
for (int i = 0; i < length; i++) { 
    synchronized(list) { 
    letter = list.get(i); 
    } 
    // whatever else 
} 

// code for swap 
synchronized(list) { 
    list.remove(F); 
    list.add(0,F); 
} 

更新

我假設你需要循環線程看到你在你的交換/循環代碼進行更改。那是對的嗎?

如果不是,他們可以簡單地克隆/複製列表供您自己使用。

List copy = new ArrayList(list); 
copy.remove(F); 
copy.add(0,F); 
+0

您好sudocode,我沒有自己的循環代碼,只有交換(這是一個運動,而不是交換)。如果我只同步交換,我是否仍然存在競爭狀態?謝謝 – Akira

+0

如果你不擁有循環代碼,並且它不在列表上同步,那麼你不能安全地在你自己的線程上修改列表。 – sudocode

0

重新排序的對象ArrayList中,但不使用add()remove()或可改變的大小的任何其它方法。

這是可以做到的,而粗暴,如下:

Object temp = F; 

for (int i = list.indexOf(F); i > 0; i--) { 
    list.set(i, list.get(i - 1)); 
} 

list.set(0, temp); 

但是請注意,在其他線程中的循環可能會遇到錯誤的順序中的對象,或在不同的位置相同的對象。如果其他線程添加或刪除項目,那麼這是行不通的。

我想如果你不能同步列表,你可能不應該試圖從你的線程修改它。

相關問題