SwingWorker 在方法 LockSupport.park() 中等待很长时间

Posted

技术标签:

【中文标题】SwingWorker 在方法 LockSupport.park() 中等待很长时间【英文标题】:SwingWorker Waiting Long Time in Method LockSupport.park() 【发布时间】:2019-10-26 09:02:10 【问题描述】:

我在具有 8 GB RAM 的 Windows 10 64 位上使用 JDK 1.8。 我有一个 Swing 应用程序。 在应用程序中,我查询了一个 DB2 数据库。 该查询返回每个表的数据库表名称和查询条件的列表。 这些表存在于单独的 SQL Server Express 数据库中。 我的 Swing 应用程序为每个 SQL Server Express 数据库表创建一个单独的 JComboBox,并使用接收到的条件查询该表,并使用查询结果填充 JComboBox 模型。 我遍历 DB2 查询的结果,并为每一行创建一个新的 JComboBox 并启动一个新的 SwingWorker 来查询 SQL Server Express 数据库。 最初我的应用程序在 Windows 7 上使用 JDK 1.5 运行。 当然SwingWorker 在 1.5 版中不是 JDK 的一部分,所以我使用了第三方实现。 原始版本运行良好,但是在 Windows 10 上迁移到 JDK 1.8 后,完成所有这些初始化需要更多时间。 使用 VisualVM,时间增加是由于 SwingWorker 线程在类 LockSupport 的方法 park() 中等待。 我测量了执行过程中每个单独步骤所花费的时间,其中大多数需要百分之几秒才能完成,所有步骤的总时间不超过三秒。 我尝试在 JDK 1.8 版本中使用我的 JDK 1.5 应用程序中的 SwingWorker 实现,但所用时间没有改变。 我怎样才能发现是什么导致某些SwingWorker 线程在方法park() 中花费大约6 秒? 或者,我怎样才能改变我的设计以避免这个问题?

部分[伪]代码...

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 屏幕截图:

【问题讨论】:

你关闭 SQL 连接了吗? @MikhailIonkin 是的,我关闭了所有 SQL 连接。 原来问题是我在 Windows 10 64 位上使用 JDK 1.8 32 位编译和运行。 【参考方案1】:

可以看到LinkedBlockingQueue.take()上被阻塞了,也就是说队列是空的,所以在等待。这是完全正常和正确的。

您的问题出在其他地方。

现在你说你测量了时间,总时间约为 3 秒,但你暗示它实际上比这慢。我假设您的意思是获得响应式 GUI 需要超过 3 秒的时间。在这种情况下,听起来您实际上并未测量所有步骤。例如,如果您要创建一个新的 Connection 对象而不是从池中获取一个对象,这会非常慢,但除非您知道要查找它,否则它可能不会轻易出现在 VisualVM 中。

最后,您可能会遇到类似LockSupport.park() 这样的线程争用问题,但了解它的用途很重要。在您的示例中,您有一个没有工作要做的工作线程,所以它正在睡觉。例如,它与死锁完全不同,死锁会显示为两个停放的线程(等待彼此的锁)。

那么为什么它以前有效?也许它是偶然的,而不是设计的。也许 Java 版本无关紧要,而您更改了其他内容。

【讨论】:

您的问题出在其他地方 也许您可以建议在哪里查看代码,以便尝试发现为什么队列空了这么长时间? (请参阅我在问题中发布的伪代码。) @Abra 队列为空并没有什么问题,特别是如果您有这么多工作线程(屏幕截图显示至少 2 个池,每个池至少 6 个线程)。您做错了什么(我不知道是什么,因为伪代码不是真正的代码),并且您误解了 VisualVM 的结果。 你做错了 same 代码在 Java 1.5 中运行良好。 @Abra 好的有人做错了。但正如我所解释的,visualvm 截图中没有什么奇怪的。工作线程正在等待,因为没有工作要做。如果你不能提供更多的细节,就不可能提供更多的帮助。 如果你不能提供更多的细节,就不可能提供更多的帮助。给我一个提示。您希望我提供哪些详细信息?

以上是关于SwingWorker 在方法 LockSupport.park() 中等待很长时间的主要内容,如果未能解决你的问题,请参考以下文章

发布/处理使 SwingWorker 变慢

JavaFX SwingWorker 等价物?

如果使用 SwingWorker 加载数据,何时将 TabelModel 绑定到 JTable?

java swingworker线程更新main Gui

java - JLabel setForeground 在 SwingWorker 中不起作用

等待多个 SwingWorker