Что если большое количество объектов будет передано в мой метод SwingWorker.process ()? - PullRequest
3 голосов
/ 28 мая 2010

Я только что нашел интересную ситуацию. Предположим, у вас есть какой-то 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) и к тому времени, когда вы обрабатываете каждый объект, вы потратили 20 секунд в потоке рассылки событий, именно то, что SwingWorker был разработан, чтобы избежать.

В случае, если неясно, оба они происходят в одном и том же классе SwingWorker для меня - это зависит от входных данных и типа обработки, которую хотел вызывающий.

Есть ли правильный способ справиться с этим? Очевидно, я могу намеренно задержать или выдать поток фоновой обработки, чтобы каждый раз приходило меньшее число , но для меня это не является правильным решением.

Ответы [ 2 ]

4 голосов
/ 28 мая 2010

Вы можете попробовать опубликовать меньшие фрагменты результатов.

Если это не поможет, вы можете также рассмотреть возможность регулирования обновлений пользовательского интерфейса вместо вычислений. Вы можете модерировать обновление пользовательского интерфейса, если process сохранит полученные пары NodePairs в очередь блокировки:

@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 извлекает и публикует NodePairs из очереди дросселированным способом.

2 голосов
/ 28 мая 2010

Насколько мне известно, метод процесса заключается в основном в обновлении пользовательского интерфейса с результатами фоновой обработки. В случае с блоком 1Mio меня интересует, где вся эта информация будет отображаться на экране? :-)

Я бы собрал куски в большой список и отправил их на обработку, чтобы, по крайней мере, часть синхронизации была значительно уменьшена.

Если вам нужно иметь возможность отображать элементы данных 1Mio с помощью элементов управления, производительность все равно будет снижаться, если вы не будете использовать методы отложенного представления, то есть только создавать экземпляры того материала, который действительно виден. В этом случае процедура процесса больше не будет перегружена.

...