2016-04-27 68 views
1

有什麼清潔和有效的方式來種植Atomic(Double|Integer|Long|Reference)Array?在我的特殊情況下,複製期間沒有併發寫入。一個顯而易見的方法來創建一個新的和源陣列複製到目標數組中的一個循環:高效增長的原子陣列

Atomic*Array dest = new Atomic*Array(newSize); 
for (int i = 0, len = src.length(); i < len; ++i) 
    dest.set(i, src.get(i)); 

該代碼很可能不是System.arraycopyArrays.copy類型的函數慢得多,也有點冗長。

我可以交替使用反射來獲取源的array領域,擴展它,而新的數組傳遞到原子* Array構造:

try { 
    Field arrayField = Atomic*Array.class.getDeclaredField("array"); 
    arrayField.setAccessible(true); 
    ArrayType srcArray = (ArrayType)arrayField.get(src); 
    Atomic*Array dest = new Atomic*Array(Arrays.copyOf(srcArray, newLength)); 
} catch (IllegalAccessException | NoSuchFieldException e) { 
    throw new AssertionError(e); 
} 

但是這個代碼有問題,太:這取決於執行的Atomic*Array類,使數組的兩個副本 - 一個在Arrays.copy和一個在dest的構造函數中,並且非常難看。

有沒有更快/更乾淨的方法來做到這一點?

+0

相關:http://stackoverflow.com/questions/9408112/get-the-array-from-an-atomiclongarray –

+0

你可以通過鏈接從舊到新的數組,以便消費者可以遍歷。有關此想法的示例,請參閱JCTools的[MpscChunkedArrayQueue](https://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/queues/MpscChunkedArrayQueue.java)。 –

+0

@BenManes是的,我想到了這個想法,但是由於我們需要在鏈接中包裝數組,因此內存使用量要高得多,而且邏輯稍微複雜一點,因爲我們需要維護一個近似的尾指針。正如事情正在一個單一的陣列正常工作,但我想盡可能多的表現這種方法儘可能。 –

回答

1

我很擔心我會讓你失望的:沒有辦法如何批量複製Atomic*Array

看看javadoc,沒有一種方法可以給你一次以上的單個元素。即使使用原始數組,您也可以傳遞給AtomicIntegerArray構造函數,這將有助於 - 該類在內部創建副本。

AtomicIntegerArray源代碼,使用反射可以工作 - 類不會做任何特殊的array字段。不過,我不會。它不僅是不安全的,而且反射會給你一些你試圖避免的性能損失。

如果您的目標是增加陣列,您可能需要查看LinkedBlockingQueueCopyOnWriteArrayList,具體取決於您的使用情況。

我已經跑了幾次這個問題,我們總是找到一種方式,最終沒有Atomic*Array

+0

謝謝。我的目標是實現一個非常有效的,非阻塞的僅附加列表。但不幸的是'LinkedBlockingQueue'和'CopyOnWriteArrayList'都不能滿足我的需求:前者爲節點使用太多的內存,而後者效率極低。事實上,標準庫中的集合都不符合我的要求。 –

+0

太糟糕了,你添加了「非阻塞」的要求,否則你也可以用舊的'synchronized'做:) – Mifeet

+0

Right,'Collections.synchronizedList(new ArrayList <>())'會工作,但非阻塞是因爲絕大多數時間沒有爭用,因此速度明顯更快(即使通過循環複製增長)。 –