1

我有一个关于我一直在研究和寻找答案的事情的一般性问题 3 天(并且基本上已经放弃了纯粹的挫败感。)

情景1;

A) 调用方法创建并显示“请稍候..”带有 .setVisible(true) 的 JWindow 组件

B)调用方法进行简单的计算和 System.out 的结果

C)“请稍候..”在步骤 B 执行期间按预期持续存在

D) 步骤 B 终止并在“请稍候”窗口上调用 .setVisible(false) 并按预期进行

到目前为止,一切都很好。

情景2;

与场景 1 相同,只是步骤 B 中的工作要复杂得多,并调用一个自定义类,该类执行一堆数据库查询/写入,平均大约需要 3-6 秒才能完成。自定义类不可运行或线程化,只是简单地调用;

customClass cc = new customClass();
cc.makeMyDataPlease();
  • 无论出于何种原因,在方案 2 中,.setVisible(true) 步骤 'A' 直到复杂的工作步骤 'B' 完成后才会发生。

我现在已经花了 2 1/2 整整一天的时间来尝试解决在本网站上找到的这些类型问题的许多解决方案,而其他人却没有运气。尝试了 swingworker、invokelater、thread 等,并得出结论,在撕掉更多头发之前,我需要对此进行更多调查。

对于连接到 URL 并发布数据的方法,我遇到了类似的问题。在网络连接例程开始之前,我试图在一个简单的 JLabel 上设置文本,但它也失败了。文本是在网络例程完成后设置的。

就好像虚拟机正在线程化每个语句执行。

我的怀疑是 mysql 类和网络 URL 类共享属性(网络?)冻结可能没有时间完成的其他任务。

这是我的问题/困惑:

如果除非创建/调用新线程,否则主 java 线程中的执行是顺序的,为什么会有任何干扰该 setVisible(true) 语句?它在逻辑上必须在执行数据库例程语句之前完成,但事实并非如此。

java中确保一个语句在下一个语句之前完全执行的最终方法是什么?(或者至少,当下一个开始时,我确信 VM 可以足够快地执行 setVisible,以至于它们甚至可以同步启动)。

提前致谢

具体来说,我的问题是;在处理与 Java 中的“阻塞器”例程相关的并发问题以及如何在这些范围内最好地工作时,最佳实践是什么。

4

1 回答 1

2

与场景 1 相同,只是步骤 B 中的工作要复杂得多,并调用一个自定义类,该类执行一堆数据库查询/写入,平均大约需要 3-6 秒才能完成。自定义类不可运行或线程化,只是简单地调用;

customClass cc = new customClass(); cc.makeMyDataPlease(); 无论出于何种原因,在方案 2 中,.setVisible(true) 步骤 'A' 直到复杂的工作步骤 'B' 完成后才会发生。

问题是,Swing 是一个单线程环境。与 UI 的所有交互都应在事件调度线程的上下文中执行。任何阻塞该线程的进程都会阻止它处理新事件,包括绘制请求。

发生的情况是,场景 2 很可能会阻止 EDT,阻止它显示窗口,但是,当您完成所有处理时,EDT 会在打开事件之后立即响应关闭事件。

由于框架的结构方式,您必须确保;

  1. 对 UI 的所有交互和修改都在 EDT 内完成
  2. 任何长时间运行或阻塞的进程都是在 EDT 之外完成的。

首先查看Swing 中的并发以了解更多详细信息。

没有进一步的证据,我的直觉是使用SwingWorker

例如...

import java.awt.EventQueue;
import java.util.concurrent.ExecutionException;
import javax.swing.JLabel;
import javax.swing.JWindow;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class QuickWorker {

    public static void main(String[] args) {
        new QuickWorker();
    }

    public QuickWorker() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JWindow window = new JWindow();
                window.add(new JLabel("Look no hands!"));
                window.pack();
                window.setLocationRelativeTo(null);

            }
        });
    }

    public class Worker extends SwingWorker<Object, Object> {

        private JWindow window;

        public Worker(JWindow window) {
            this.window = window;
        }

        @Override
        protected Object doInBackground() throws Exception {
            // Long running process...
            Thread.sleep(5000);
            return "All done";
        }

        @Override
        protected void done() {
            try {
                // Get the results of the process if you want them...
                get();
            } catch (InterruptedException | ExecutionException ex) {
                ex.printStackTrace();
            }
            window.dispose();
            // This is only here because the example will keep running without it :P
            System.exit(0);
        }
    }
}
于 2013-10-14T02:36:02.060 回答