java - 如何在不阻塞 EDT 的情况下等待 EDT 中的对象创建?

标签 java swing concurrency swingworker edt

我在 Java 库中使用一个 API,它从事件分派(dispatch)线程调用​​并要求我返回一个完全初始化的 UI 组件。它看起来像这样:

public JDialog createDialog();

但我只能在从数据库加载后填充对话框,有时这可能需要 10 秒。通常我会在后台线程中执行此操作,但由于此方法是从 EDT 调用的,并且由于我必须返回对话框,因此无法正常工作。这是一个第三方库,所以我无法更改方法,但我能做些什么来避免阻止 EDT 吗?

最佳答案

“已初始化”不一定与“已填充”相同。 “已初始化”通常表示对象已经完全构造完毕,但可能还没有任何数据。 “已填充”当然意味着数据存在并且任何数据获取任务都已完成。因此,可以为您的第三方库提供一个完全初始化的 JDialog,而根本没有任何数据。

我一直喜欢解决这个问题的方法是创建一个自定义的JDialog,显示忙音或进度条之类的,然后在另一个线程中请求数据。返回数据时,我用数据替换忙消息(在 EDT 上!)。至于你应该如何在后台线程中执行你的请求,我建议使用 SwingWorkers。我喜欢在我的自定义 JDialog 中使用一个私有(private)的 SwingWorker,它在 doInBackground() 方法中处理请求,并在 done( ) 方法。这样做将确保与显示相关的任务仅在 EDT 上发生,而与数据库相关的任务仅在 EDT 之外发生。如果您想获得有关使用 SwingWorkers 的相当不错的介绍,请查看 Sun's tutorial on worker threads .一个简单的例子是:

public class DBDIalog extends JDialog{
     private JLabel busyLabel = new JLabel("Fetching data from DataBase");
     
     public DBDialog(){
         //do your initialization stuff here
     }

     private class DBFetcher extends SwingWorker<Void,DBInfo>{
         
        @Override
        protected DBInfo doInBackground() throws Exception{
            return fetchDataFromDB(); //or whatever database call to make
        }

        @Override
        protected void done(){
           try{
               DBInfo info = get();
           //replace your busy label with your DBInfo
           }catch(InterruptedException e){
              //do appropriate thread interrupted stuff
           }catch(ExecutionException e){
              //do appropriate general error handling stuff 
           }

        }
     }
}

但有几件事要记住:done() 方法不是抽象的,因此您不需要覆盖它。不过,你应该。如果您的 doInBackground() 实现抛出异常,除非 done() 被覆盖,否则该异常将被吞没。另外,不要从 doInBackground() 中更改您的 GUI,除非您使用 SwingUtilities.invokeLater(Runnable),如 doInBackground() 是从与 EDT 不同的线程执行的,从后台线程更改 GUI 会产生奇怪且无法解释的错误。

应该在什么时候使用?与其他编程任务不同,在 GUI 中响应时间过长的时间点要短得多——我通常看到的数字是 250 毫秒左右。如果您的任务花费的时间比这更长,则它应该在后台线程中。在你的情况下,10 秒应该绝对在后台线程中,但是你已经知道了:)

编辑:

看到您的评论,我发现我的大部分帖子都没有实际意义。但是,您仍然可以使用 SwingWorker:

让您的 SwingWorker 执行数据检索,并在 done() 方法中,让它从数据构造 JDialog 并将该对话框交给您的第三方库。

关于java - 如何在不阻塞 EDT 的情况下等待 EDT 中的对象创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1987034/

相关文章:

java - jbutton 请求并发无响应

java - 使用 Java 泛型引用当前类型

java - Java中类与类之间传递变量

java - JCheckbox 被选择时不显示标签中的文本

java - JCheckBox 的值重置/不变

java - 线程没有被终止;陷入循环

使用ConcurrentLinkedQueue的Java线程问题

java - 一个正则表达式,用于捕获两个略有不同的模式

java - 如何比较两个数组列表并提取第三个数组列表中两个数组中不常见的元素

java - 使用 MigLayout 调整组件和字体的大小