2010-05-28 4 views
3

Я только нашел интересную ситуацию. Предположим, у вас есть SwingWorker (я сделал это один смутно напоминающий мой собственный):Что делать, если большое количество объектов передается моему методу SwingWorker.process()?

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 для меня - это зависит от входных данных и типа обработки запроса.

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

ответ

4

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

Если это не поможет, вы можете также рассмотреть возможность изменения обновлений пользовательского интерфейса вместо вычисления. Вы можете модерировать обновление пользовательского интерфейса при наличии 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

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

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

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

Смежные вопросы