2011-09-02 48 views
1

我想用更高性能的東西替換未來實例列表。目前我正在遍歷樹並提交一個Callable來確定樹中每個節點的後代或自身節點的數量。我在一個列表保存未來的實例,然後得到一次所需的列表中選擇合適的節點計數:未來實例列表

try { 
    assert mIndex + 1 < mDescendants.size(); 
    mItem = 
     Item.BUILDER.set(mAngle, mExtension, mIndexToParent).setParentDescendantCount(
       mParDescendantCount).setDescendantCount(mDescendants.get(mIndex + 1).get()).build(); 
} catch (final InterruptedException | ExecutionException e) { 
    LOGWRAPPER.error(e.getMessage(), e); 
} 

可悲的是,這是利用了列表的軸必須等待,直到所有的未來實例已提交。此外,它不會超出主存限制: -/

也許Google Guava和ListenableFuture是正確的使用方法。

編輯:現在我想我會用PropertyChangeListener構建一些東西,只要Future被激發,Futures就會被添加到列表中。然後,我將CountDownLatch初始化爲1,並在每次將新的Future添加到列表中時調用countDown()。喜歡的東西:

/** 
* {@inheritDoc} 
*/ 
@Override 
public boolean hasNext() { 
    if (mDescendants.size() > 0) { 
     return doHasNext(); 
    } else { 
     try { 
      mLatch.await(5, TimeUnit.SECONDS); 
     } catch (final InterruptedException e) { 
      LOGWRAPPER.error(e.getMessage(), e); 
     } 
     return doHasNext(); 
    } 
} 

然後doHasNext():

try { 
    assert mIndex + 1 < mDescendants.size(); 
    mItem = 
     Item.BUILDER.set(mAngle, mExtension, mIndexToParent).setParentDescendantCount(
       mParDescendantCount).setDescendantCount(mDescendants.get(mIndex + 1).get()).build(); 
    mLatch = new CountDownLatch(1); 
} catch (final InterruptedException | ExecutionException e) { 
    LOGWRAPPER.error(e.getMessage(), e); 
} 

和監聽器:

/** {@inheritDoc} */ 
@SuppressWarnings("unchecked") 
@Override 
public void propertyChange(final PropertyChangeEvent paramEvent) { 
    Objects.requireNonNull(paramEvent); 

    if ("descendants".equals(paramEvent.getPropertyName())) { 
     mDescendants.add((Future<Integer>) paramEvent.getNewValue()); 
     mLatch.countDown(); 
    } 
} 

我不知道,如果它的工作原理,這是爲時已晚,我猜疑我會使用CountDownLatch(沒有測試過上面的代碼)。

編輯:以防萬一有人感興趣。現在,我不再使用CountDownLatch和List,而是簡單地將BlockingQueue與PropertyChangeListener的實現結合使用,這似乎是一個很好的「乾淨」解決方案。

問候,

約翰內斯

+0

我不太瞭解你提交的代碼(Item.BUILDER做什麼?),但是,如果你的List太大而不適合內存,一個可能的解決方案是重寫你的代碼來處理迭代器/迭代器,並處理你的項目。 Guava在com.google.common.collect.Iterables和com.google.common.collect.Iterators中提供了許多實用的方法來幫助您做到這一點。 –

+0

「功能實例」 - >您的意思是未來的實例,對吧? – jvdneste

回答

2

你就不能使用completion service?一旦提交,它將處理第一個未來完成...

+0

不,我需要它們,這就是爲什麼我認爲這是使用觀察者模式和BlockingQueue的最佳方式。這只是一個管道或東西,它顯然更快。現在我只需要替換另一個瓶頸,當所有物品都已經生產完畢,我就會發生變化,這是浪費時間。 – Johannes

+0

如果您需要它們以特定順序完成,是不是隻是序列號?即,爲什麼不等待每個未來呢?這種影響與使用觀察者不一樣?並更簡單..?我建議提交工作不應該是一個巨大的開銷,它很可能被等待每個工作完成的時間所壓倒。 – Toby

+0

對於較大的樹木(尤其是1MB及以上版本 - 如果可能將其視爲較大的樹木),它似乎會產生巨大差異。它顯然似乎更好,因爲即使對於大約2000個節點,樹的遍歷和提交似乎持續大約2到3秒,但我沒有對它進行基準測試。由於這種流水線方法加速了整個流程:-) – Johannes