SwingWorker долгое время ждет в методе LockSupport.park () - PullRequest
0 голосов
/ 26 октября 2019

Я использую JDK 1.8 в Windows 10 64-разрядная с 8 ГБ оперативной памяти. У меня есть приложение Swing . В приложении я запрашиваю базу данных DB2. Запрос возвращает список имен таблиц базы данных и критерии запроса для каждой таблицы. Эти таблицы существуют в отдельной базе данных SQL Server Express. Мое приложение Swing создает отдельную JComboBox для каждой таблицы базы данных SQL Server Express и запрашивает эту таблицу, используя полученные критерии, и заполняет модель JComboBox результатами запроса. Я перебираю результаты запроса DB2 и для каждой строки создаю новый JComboBox и запускаю новый SwingWorker для запроса базы данных SQL Server Express. Первоначально мое приложение работало с JDK 1.5 в Windows 7. Конечно, SwingWorker не было частью JDK в версии 1.5, поэтому я использовал стороннюю реализацию. Оригинал работает нормально, однако после перехода на JDK 1.8 в Windows 10 потребуется гораздо больше времени для завершения всей этой инициализации. В VisualVM увеличение времени происходит из-за потоков SwingWorker, ожидающих в методе park() класса LockSupport. Я измерил время, затрачиваемое на выполнение каждого отдельного шага в процессе, и большинству из них требуется несколько сотых долей секунды, чтобы завершить общее время для всех шагов, не превышающее трех секунд. Я пытался использовать реализацию SwingWorker из моего приложения JDK 1.5 в версии JDK 1.8, но время не изменилось. Как я могу узнать, что заставляет некоторые потоки SwingWorker тратить около 6 секунд в методе park()? Кроме того, как я могу изменить свой дизайн, чтобы избежать этой проблемы?

Частичный [псевдокод] код ...

JPanel panel = new JPanel();
Connection db2Conn = // Connect to DB2
Statement s = db2Conn.createStatement();
ResultSet rs = s.executeQuery("SQL query");
while (rs.next()) {
    new ListTask(panel, /* data from 'rs' */).execute();
}

class ListTask extends SwingWorker<Void, Void> {
    // JComboBox will be added to this. See method 'done()'
    private JPanel panel;

    // Name of table in database.
    private String tableName;

    // Criteria for querying 'tableName'.
    private List<String> criteria;

    // Results of query.
    private Object[] results;

    public ListTask(JPanel aPanel, String table, List<String> where) {
        panel = aPanel;
        tableName = table;
        criteria = where;
    }

    protected void doInBackground() {
        // Populate "results"
        return null;
    }

    protected void done() {
        JComboBox<Object> combo = new JComboBox(results);
        panel.add(combo);
    }
}

Снимок экрана VisualVM:

VisualVM Screen Capture

1 Ответ

0 голосов
/ 26 октября 2019

Вы можете видеть, что он заблокирован на LinkedBlockingQueue.take(), что означает, что очередь пуста, поэтому она ожидает. Это совершенно нормально и правильно.

Ваша проблема в другом месте.

Теперь вы говорите, что вы измерили время, а общее время составляет около 3 секунд, но затем вы подразумеваете, чтоэто на самом деле медленнее, чем это. Я полагаю, вы имеете в виду, что для получения адаптивного графического интерфейса требуется более 3 секунд. В этом случае кажется, что вы на самом деле не измерили все шагов. Например, если вы создаете новый Connection объект, а не получаете его из пула, это очень медленно, но он может не отображаться легко в VisualVM, если вы не знаете, как его искать.

Наконец, вымогут возникнуть проблемы с конфликтами потоков, которые могут появиться с чем-то вроде LockSupport.park(), но важно понимать, для чего он используется. В вашем примере у вас есть рабочий поток, который не имеет работы, поэтому он спит. Например, это очень сильно отличается от тупика, который будет отображаться как два припаркованных потока (ожидающих блокировки друг друга).

Так почему же он работал раньше? Может быть, это сработало случайно, а не по замыслу. Возможно, версия Java не имеет значения, и вы изменили что-то еще.

...