3

我刚刚发现了一个有趣的情况。假设你有一些 SwingWorker (我让这个有点让人想起我自己的):

public class AddressTreeBuildingWorker extends SwingWorker<Void, NodePair> {
    private DefaultTreeModel model;
    public AddressTreeBuildingWorker(DefaultTreeModel model) {
    }

    @Override
    protected Void doInBackground() {
        // Omitted; performs variable processing to build a tree of address nodes.
    }

    @Override
    protected void process(List<NodePair> chunks) {
        for (NodePair pair : chunks) {
            // Actually the real thing inserts in order.
            model.insertNodeInto(parent, child, parent.getChildCount());
        }
    }

    private static class NodePair {
        private final DefaultMutableTreeNode parent;
        private final DefaultMutableTreeNode child;
        private NodePair(DefaultMutableTreeNode parent, DefaultMutableTreeNode child) {
            this.parent = parent;
            this.child = child;
        }
    }
}

如果在后台完成的工作很重要,那么事情就会很好 -process()用相对较少的对象列表调用并且一切都很愉快。

问题是,如果在后台完成的工作由于某种原因突然变得微不足道,process()会收到一个巨大的对象列表(例如,我见过 1,000,000 个),并且当您处理每个对象时,您已经在 Event Dispatch 上花费了 20 秒线程,正是 SwingWorker 旨在避免的。

如果不清楚,对我来说,这两者都发生在同一个 SwingWorker 类上——这取决于输入数据和调用者想要的处理类型。

有没有合适的方法来处理这个?显然,我可以故意延迟或让出后台处理线程,以便每次可能有更少的线程到达,但这对我来说并不是正确的解决方案。

4

2 回答 2

4

您可以尝试发布较小的结果块。

如果这没有帮助,您还可以考虑限制 UI 更新而不是计算。process您可以通过将接收到的 NodePair 存储到阻塞队列中来缓和 UI 更新:

@Override
protected Void doInBackground() {
    this.treeModelUpdater.execute();
    // Omitted; performs variable processing to build a tree of address nodes.
}

@Override
protected void process(List<NodePair> chunks) {
    this.queue.addAll( chunks ); // a blocking queue
}

@Override
protected void done() {
    // Null Object as sentinel value to unblock TreeModelUpdater
    // and signal it to end doInBackground.
    this.queue.put( new NullNodePair() );
}

TreeModelUpdater ( this.treeModelUpdater) 将成为从属 SwingWorker 实现,其 doInBackground方法以节流的方式从队列中检索和发布 NodePair。

于 2010-05-28T02:20:06.137 回答
2

据我所知,处理方法主要是用后台处理的结果更新UI。在 1Mio 块的情况下,我想知道所有这些信息会在屏幕上显示在哪里?:-)

我会在一个相当大的列表中将这些块一起批量处理,然后将其发送出去进行处理,这样至少同步部分会显着减少。

如果您需要能够使用控件显示 1Mio 数据元素,那么性能无论如何都会受到影响,除非您使用惰性表示技术,即仅实例化实际可见的内容。在这种情况下,流程例程将不再过载。

于 2010-05-28T01:30:31.720 回答