Swing Worker和普通线程之间的区别?

时间:2014-11-10 04:25:07

标签: java multithreading swing swingworker

根据我之前的问题What's the best way to have a dynamic JTable whose data updates itself with changes in database table?,我使用以下代码自动更新jList

       DefaultListModel x = new DefaultListModel();
       jList1.setModel(x);
       int initialDelay = 0;
       int period = 5000;
       Timer timer = new Timer();
       TimerTask task = new TimerTask() {

        public void run() {
            x.clear();
            try {
                conn = Database.Connect("patient.db");
                sql = "SELECT * FROM PATIENT_APPOINTMENTS";
                pst = conn.prepareStatement(sql);
                rs = pst.executeQuery();

                while(rs.next()) {

                    x.addElement(rs.getString("patientid"));

                }


            }
            catch ( Exception e) {

                JOptionPane.showMessageDialog(null,e,"Error",JOptionPane.ERROR_MESSAGE);
            }
        }
    };
    timer.scheduleAtFixedRate(task,initialDelay,period);

但是我已经阅读了有关SwingWorker的内容,它似乎是正确的方法。swing工作程序的正常实现有3个受保护的doInBackground方法,发布和完成。我还尝试使用SwingWorker的另一个版本

    DefaultListModel x = new DefaultListModel();
    jList1.setModel(x);

    int initialDelay = 0;
    int period = 5000;
    Timer timer = new Timer();
    TimerTask task = new TimerTask() {

        public void run() {
            x.clear();

            try {

                SwingWorker<ArrayList<String>, Void> worker = new SwingWorker<ArrayList<String>, Void>() {

                    protected ArrayList<String> doInBackground() throws Exception {

                        ArrayList<String> patientid = new ArrayList<String>();
                        conn = Database.Connect("patient.db");
                        sql = "SELECT * FROM PATIENT_APPOINTMENTS";
                        pst = conn.prepareStatement(sql);
                        rs = pst.executeQuery();

                        while (rs.next()) {

                            patientid.add(rs.getString("patientid"));

                        }

                        return patientid;
                    }

                    protected void done() {

                        ArrayList<String> id = new ArrayList<String>();
                        try {

                            id = get();
                            for (int i = 0; i < id.size(); i++) {
                                x.addElement(id.get(i));
                            }

                        } catch (InterruptedException e) {

                            JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
                        } catch (ExecutionException e) {
                            JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
                        }
                    }

                };
                worker.execute();
            } catch (Exception e) {

                JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
            }

        }
    };
    timer.scheduleAtFixedRate(task, initialDelay, period);
}

哪种方法比较好? 此外,jList每5秒闪烁5次,我该如何避免?

1 个答案:

答案 0 :(得分:5)

Swing Timer在Event Dispatching Thread的上下文中执行它的通知,使其适合更新UI,但不适合执行长时间运行或阻塞任务(如查询数据库)

Thread适用于执行长时间运行或阻止任务但不应该用于更新UI,因为Swing不是线程安全的,并且只应在EDT的上下文中修改UI。当然你可以使用EventQueue.invokeLater,但是如果你需要为这些调用提供参数会很痛苦......

您可以改为使用SwingWorker,它有能力在后台执行长时间运行或阻止任务(在EDT之外),但提供了通过它{{1}更新UI的方法} / publishprocess和/或done支持

看看:

了解更多详情

  

哪种方法更好

您的第一个示例违反了Swing的单线程规则,因此没有多大用处......

你的第二个例子是过度杀戮,PropertyChange已经在运行背景,你实际上更善于使用ScheduledExecutorService并传递TimerTask的实例。

<强>更新

不是我喜欢它的方式,但......

SwingWorker