SwingWorker在完成后挂起:从SwingWorker启动和运行线程池是否是一种不好的做法?

posdef

假设应用程序读取数据文件,从用户那里获取一些输入(通过GUI),从大型数据库中获取其他数据,然后进行冗长的分析。

按照建议,我将耗时的部分(数据库管理和实际分析)移到了SwingWorker实例中。现在,执行数据库管理的第一部分工作正常(请参见下面的代码):

dialog.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosed(WindowEvent e) {
            final File dbFile = dialog.getFile();

            frame.activateDisGlass("Loading DB, please wait...");
            SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    try {
                        dbman = new DbManager(dbFile);
                    } catch (SQLException e1) {
                        System.err.println("Unable to load the chosen database, see details below:");
                        e1.printStackTrace();
                    }
                    return null;
                }

                @Override
                protected void done(){
                    frame.deactivateDisGlass();
                }
            };              
            worker.execute();           
        }
    });

但是,相同的策略在分析情况下无法正常工作。由于分析篇幅很长,并且涉及许多自定义类,因此我将总结一下情况。以下代码位于一个自定义类中,该类与GUI交互以获取用户输入,使用触发计算analyzeButton,该初始化创建多个对象的创建,其中一个对象包含线程池以并行执行独立分析:

// INITIATE ANALYSIS
    analyzeButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {

            for (int i = 0; i < annots.length; i++) {
                annots[i] = (ANNOT_TYPE) combos[i].getSelectedItem();
            }

            // Validate the column annotations
            List<ANNOT_TYPE> annotlist = Arrays.asList(annots);
            if (!annotlist.contains(ANNOT_TYPE.R) &&
                !(annotlist.contains(ANNOT_TYPE.OS1) && 
                        annotlist.contains(ANNOT_TYPE.OS2))) {
                JOptionPane
                        .showMessageDialog(
                                null,
                                "<html>Missing annotation!<p>"
                                        + "<p> Please make sure you have annotated the datafile correctly...",
                                "Missing annotation!",
                                JOptionPane.ERROR_MESSAGE);
                return;
            }

            // Validate DB selection
            if (descPanel.getDBManager() == null) {
                JOptionPane
                        .showMessageDialog(
                                null,
                                "<html>No database not selected for analysis! <p>"
                                        + "<p> Please select and load a database..",
                                "Database error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            // Activate progress indicator
            frame.getMainFrame().activateInfiGlass();

            SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() {
                    try {
                        // register parameters
                        param.addParam(AnalysisParams.value_key,descPanel.getValueTypeComboIndex());
                        param.addParam(AnalysisParams.sepchar_key,descPanel.getSepCharComboIndex());
                        paramPanel.registerParams();

                        StringBuilder sb = new StringBuilder("Data preview completed, initiating analysis...");
                        sb.append(System.lineSeparator())
                            .append("... column annotations: ")
                            .append(Arrays.toString(annots));
                        logger.info(sb.toString() + System.lineSeparator());

                        // Create dataset; to be passed on to SwingWorker which will
                        // execute the analysis
                        ds = new Dataset();

                        for (String[] line : data)
                            ds.addRow(line, annots);

                        System.out.println("Dataset parsed...");
                        logger.info("Dataset parsing complete "
                                + System.lineSeparator() 
                                + ds.toString()
                                + System.lineSeparator());

                        conserv = new ConcurrencyService(ds, descPanel.getDBManager());
                        conserv.serve();
                        DebugToolbox.dumpScores();                          
                        }
                    } catch (InterruptedException e) {
                        logger.severe("Concurrency service interrupted"
                                + System.lineSeparator()
                                + e.getStackTrace()
                                + System.lineSeparator());
                        System.err.println("Interrupt exception!!");
                    }
                    return null;
                }

                @Override
                protected void done() {
                    if(!conserv.isDone())
                        logger.warning("Concurrency Service is not done!" + 
                                System.lineSeparator());

                    logger.info("#DEBUG: Conserv should have been terminated by now..." + System.lineSeparator());
                    frame.getMainFrame().deactivateInfiGlass();
                }
            };

            worker.execute();

        }
    });

那么问题是什么,您可能会问...问题done()是从来没有调用过,SwingWorker而应用程序实际上只是挂起,等待某些东西。我可以看到,doInBackground()自将分数转储到日志文件以来,该操作已经完成(这是该方法的最后一步,但是我看不到预期的输出done()

我从jvisualvm得到了一个线程转储,这是相关的位:

"SwingWorker-pool-1-thread-2" daemon prio=5 tid=0x00007f8ce5819000 nid=0x860b waiting on condition [0x0000000129593000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x0000000705a2c978> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

   Locked ownable synchronizers:
    - None

前一个SwingWorker(加载数据库的那个)具有完全相同的状态和堆栈跟踪,这使我认为确实SwingWorker已经完成了工作,但是应用程序的其余部分未得到通知。

相似的问题:我注意到两个相关的问题,它们之间存在本质差异

  1. JDK-7 SwingWorker僵局?-我SwingWorker的(或应该)彼此独立。

  2. SwingWorker挂在Unsafe.park()上-我SwingWorker不与GUI交互或返回任何内容(除外null),所以它应该与无关get(),对吧?

有想法吗?

充满鳗鱼的气垫船

您声明:

所以它应该与get()没有关系,对吗?

不是这样 调用是关键,get()否则您将无法捕获和处理SwingWorker的doInBackground方法中引发的任何异常。因此,我建议您不要忘记get()done()方法中调用SwingWorker ,或者在方法中首先调用它,也不要忘记捕获和分析此方法引发的所有异常。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

SwingWorker任务完成后如何提示JOptionPane

来自分类Dev

在Java中完成SwingWorker之后启动另一个线程

来自分类Dev

目标C-多次运行方法,完成后运行另一种方法

来自分类Dev

将线程局部值保存在静态final字段中是一种不好的做法吗?

来自分类Dev

不检查获取请求是否失败是一种不好的做法吗?

来自分类Dev

在SQLalchemy中混合使用ORM和显式SQL是一种不好的做法吗?

来自分类Dev

使用大量 AngularJS 和 JavaScript 对网站来说是一种不好的做法吗?

来自分类Dev

前一个线程完成后启动另一个线程

来自分类Dev

使用通用的FindViewById是一种不好的做法吗?

来自分类Dev

使用通用的FindViewById是一种不好的做法吗?

来自分类Dev

Firebase中的静态数据是一种不好的做法?

来自分类Dev

开关盒不间断是一种不好的做法吗?

来自分类Dev

在视图中读取文件是一种不好的做法吗?

来自分类Dev

这在 PHP 中是一种不好的做法吗?

来自分类Dev

C# 属性,这是一种不好的做法吗?

来自分类Dev

旧线程完成后如何启动新线程?

来自分类Dev

完成后是否可以获得python池结果?

来自分类Dev

其他线程完成后Java再次运行线程

来自分类Dev

Rails 4:在模型中执行数据库操作是否是一种不好的做法?

来自分类Dev

仅在隐藏和更改字段的情况下在多个事件中使用相同的View是一种不好的做法吗?

来自分类Dev

结合使用Robotframework关键字和页面对象是一种好/不好的做法吗?

来自分类Dev

结合使用Robotframework关键字和页面对象是一种好/不好的做法吗?

来自分类Dev

所有子级完成后,非阻塞方法可启动多个线程并在父线程上运行callabck

来自分类Dev

使用 ThreadStart 线程完成后运行另一个函数

来自分类Dev

Java SwingWorker挂起

来自分类Dev

线程完成后如何运行Qt函数?

来自分类Dev

C++ - 在 for 循环完成后这些线程是否被销毁

来自分类Dev

有没有一种方法可以在用PHP,Javascript或HTML完成后删除表单?

来自分类Dev

systemd:服务A运行完成后如何启动服务B?

Related 相关文章

  1. 1

    SwingWorker任务完成后如何提示JOptionPane

  2. 2

    在Java中完成SwingWorker之后启动另一个线程

  3. 3

    目标C-多次运行方法,完成后运行另一种方法

  4. 4

    将线程局部值保存在静态final字段中是一种不好的做法吗?

  5. 5

    不检查获取请求是否失败是一种不好的做法吗?

  6. 6

    在SQLalchemy中混合使用ORM和显式SQL是一种不好的做法吗?

  7. 7

    使用大量 AngularJS 和 JavaScript 对网站来说是一种不好的做法吗?

  8. 8

    前一个线程完成后启动另一个线程

  9. 9

    使用通用的FindViewById是一种不好的做法吗?

  10. 10

    使用通用的FindViewById是一种不好的做法吗?

  11. 11

    Firebase中的静态数据是一种不好的做法?

  12. 12

    开关盒不间断是一种不好的做法吗?

  13. 13

    在视图中读取文件是一种不好的做法吗?

  14. 14

    这在 PHP 中是一种不好的做法吗?

  15. 15

    C# 属性,这是一种不好的做法吗?

  16. 16

    旧线程完成后如何启动新线程?

  17. 17

    完成后是否可以获得python池结果?

  18. 18

    其他线程完成后Java再次运行线程

  19. 19

    Rails 4:在模型中执行数据库操作是否是一种不好的做法?

  20. 20

    仅在隐藏和更改字段的情况下在多个事件中使用相同的View是一种不好的做法吗?

  21. 21

    结合使用Robotframework关键字和页面对象是一种好/不好的做法吗?

  22. 22

    结合使用Robotframework关键字和页面对象是一种好/不好的做法吗?

  23. 23

    所有子级完成后,非阻塞方法可启动多个线程并在父线程上运行callabck

  24. 24

    使用 ThreadStart 线程完成后运行另一个函数

  25. 25

    Java SwingWorker挂起

  26. 26

    线程完成后如何运行Qt函数?

  27. 27

    C++ - 在 for 循环完成后这些线程是否被销毁

  28. 28

    有没有一种方法可以在用PHP,Javascript或HTML完成后删除表单?

  29. 29

    systemd:服务A运行完成后如何启动服务B?

热门标签

归档