【问题标题】:Action in the concurrent thread is not executed when main thread is waiting主线程等待时不执行并发线程中的动作
【发布时间】:2011-04-07 08:13:12
【问题描述】:

我有一个使用临时表(存在于用户会话范围内)和复杂数据处理的应用程序。

出于调试目的,我需要在应用程序处理期间对此临时表执行查询。

我添加了一些额外的逻辑作为方面 (AspectJ) 并在 Eclipse 中将我的应用程序作为加载时编织应用程序运行(使用 AJDT/JDT 编织插件)。

我执行以下操作:获得新连接后,我使用 gui 创建另一个线程并将连接传递给它(稍后将描述)。

每次查询后,主应用程序线程等待来自 gui 线程的消息以继续工作(这让我有机会进行查询并在临时表中查看中间结果)。消息传递是使用 BlockingQueue 实现的。

在 GUI 中,我有一个带有用于查询的文本区域的框架和两个按钮“运行查询”和“释放主线程”。

我希望按下“运行查询”按钮将执行查询并在框架上显示结果。并按下“释放主线程”按钮将消息发送到主线程以继续工作。

问题是当主线程正在等待blockingQueue.take()时,按下“运行查询”按钮会导致框架冻结并且什么都不做(看起来gui变得没有响应)。

当主线程等待blockingQueue.take()时,“释放主线程”分叉很好(但不是在“运行查询”按下之后)。

当主线程运行时(我在队列中放了很多对象),“运行查询”按钮正常工作,我可以看到查询结果。

起初我尝试使用 EDT 和事件调度进行操作,但没有任何帮助。你对这个问题有什么想法吗?

//aspect on 'newConnection' pointcut 
after() returning (final Connection connection): newConnection()  {
    gUI = new Runnable() {
        public void run() {
            new GuiView(blockingQueue, connection);
            }
        };
    SwingUtilities.invokeLater(gUI);
}

    //GuiView code extract for button with query data retrieval action

    button.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
    try {               
      ResultSet rs = ConnectionManipulator.executeStatement(
          queryTextAreaG.getText()
      );
    ///....result parsing logic

    } catch (SQLException e1) {
        JOptionPane.showMessageDialog(null, "Exception!");
    } finally {

    }
    //....result out logic


    }
});

【问题讨论】:

  • 如果您显示一些您正在做的事情的代码,会更容易回答您的问题;您的文字描述没有为可以提供帮助的人提供足够的提示。

标签: java eclipse events swing concurrency


【解决方案1】:

GUI 通常在主线程中运行(不仅在 Java 上),因此如果您让主线程阻塞,您的 GUI 也会阻塞并且它会冻结。

编辑

我认为你弄错了 SwingUtilities.invokeLater:它被用于执行主事件循环线程中的部分代码,因此通常是从后台线程调用的,而不是相反。现在看起来查询正在事件循环线程中执行,因此阻塞了 GUI。

让查询在普通线程中执行,当它准备好时,使用 SwingUtilities.invokeLater 调用主线程回调。

【讨论】:

  • 不,带有简单操作的按钮(“释放主线程”)工作正常,即使主线程阻塞。
  • 一个谜,没有看到更多的代码我不能说什么是错的。但无论如何你不应该阻塞主线程。让查询使用回调通知主线程进入主线程。好吧,现在我有一个想法,我将编辑答案。
  • 麻烦您了。上面有描述
【解决方案2】:

对不起,麻烦了。问题出在不正确的切入点描述中(未附加到上面的代码中)。 我有这个切入点:

PreparedStatement around(): prepareStatement() {
        if (gUI != null) {
            try {
                blockingQueue.take();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {

            }
        }
return proceed(); 

ConnectionManipulator.executeStatement 也使用 prepareStatement() 。 因此它执行了blockingQueue.take(),这会导致GUI 事件线程停止。 我已经更正了切入点描述,问题就消失了。 谢谢大家。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-26
    • 2021-05-14
    • 1970-01-01
    • 2018-07-16
    • 2015-02-22
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多