未来实例列表

发布于 2024-12-02 15:18:49 字数 2171 浏览 3 评论 0原文

我想用性能更高的东西替换未来实例列表。目前,我正在遍历一棵树并提交一个 Callable 来确定树中每个节点的后代或自身节点的数量。我将 Future 实例保存在列表中,然后在需要时从列表中获取适当的节点计数:

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

可悲的是,使用列表的轴必须等到所有 Future 实例都已提交。此外,它不会超出主内存限制:-/

也许 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 的实现结合使用,这似乎是一个很好的“干净”解决方案。

问候,

约翰内斯

I'd like to replace a List of Future-Instances with something more performant. Currently I'm traversing a tree and submit a Callable to determine the number of descendant-or-self nodes for each node in the tree. I'm saving the Future instance in a List and then get the appropriate node count from the List once required:

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

The sad thing is that the axis which is making use of the List has to wait until all Future instances have been submitted. Furthermore it doesn't scale beyond main memory limits :-/

Maybe Google Guava and ListenableFuture is the right thing to use.

Edit: Now I think I'll actually build something with a PropertyChangeListener where Futures are added to a list whenever a Future is fired. Then I initiate a CountDownLatch to 1 and call countDown() everytime a new Future is added to the List. Something like:

/**
 * {@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();
    }
}

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

and the Listener:

/** {@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();
    }
}

I'm not sure if it works, it's too late and I mistrust the way I would use the CountDownLatch (haven't tested the above code).

Edit: Just in case someone is interested. Instead of the CountDownLatch and a List I now simply used a BlockingQueue in conjunction with the implementation of a PropertyChangeListener, which seems to be a good, "clean" solution.

regards,

Johannes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暗喜 2024-12-09 15:18:49

Can't you just use a completion service? Once submitted, it'll process the first future to complete...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文