简体   繁体   English

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

[英]Difference between Swing Worker and normal Threads?

As per my previous question What's the best way to have a dynamic JTable whose data updates itself with changes in database table? 根据我之前的问题,拥有动态JTable的最佳方法是什么,该JTable的数据会随着数据库表的更改而自动更新? , I have used the following code for an automatically updating jList ,我将以下代码用于自动更新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);

But I have read about SwingWorker and it seems to be the right way to do it .A normal implementation of swing worker has 3 protected methods of doInBackground , publish and done . 但是我已经阅读了有关SwingWorker的信息,这似乎是正确的方法。Swingworker的常规实现有3种受保护的方法doInBackground,publish和done。 I also tried another version with SwingWorker which is 我还尝试了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);
}

Which is the better method ? 哪个更好的方法? Further , the jList blinks once 5 every 5 seconds , how can I avoid that ? 此外,jList每5秒闪烁一次5,如何避免这种情况?

Swing Timer executes it's notifications within the context of the Event Dispatching Thread, making it suitable for updating the UI, but not suitable for executing long running or block tasks (like querying a database) Swing Timer在事件调度线程的上下文中执行其通知,使其适合于更新UI,但不适用于执行长时间运行或阻止的任务(例如查询数据库)

Thread s are suitable for executing long running or block tasks but should never be used for updating the UI, as Swing is not thread safe and the UI should only be modified from within the context of the EDT. Thread适用于执行长时间运行的任务或块任务,但绝不能用于更新UI,因为Swing并不是线程安全的,并且只能在EDT的上下文中修改UI。 Sure you can use EventQueue.invokeLater , but it becomes painful if you need to supply parameters to those calls... 当然可以使用EventQueue.invokeLater ,但是如果您需要为这些调用提供参数,它将变得很痛苦。

You could use a SwingWorker instead, which has the capacity to execute long running or blocking tasks in the background (off the EDT), but provides means by which you can update the UI, via it's publish / process , done and/or PropertyChange support 您可以改用SwingWorker ,它具有在后台执行长时间运行或阻止任务的功能(在EDT之外),但是提供了通过UI的publish / processdone和/或PropertyChange支持更新UI的process

Take a look at: 看一眼:

for more details 更多细节

Which is the better method 哪个更好的方法

Your first example violates the single thread rules of Swing, so it ain't much use... 您的第一个示例违反了Swing的单线程规则,因此它用处不大...

Your second example is over kill, the TimerTask is already running the background, you'd actually be better of using a ScheduledExecutorService and passing it an instance of the SwingWorker ... 您的第二个示例已经结束, TimerTask已经在后台运行,实际上最好使用ScheduledExecutorService并将其传递给SwingWorker一个实例。

Updated 更新

Not the way I would have liked it to work, but... 不是我希望它起作用的方式,而是...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;
        private int count;
        private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

        public TestPane() {
            setLayout(new GridBagLayout());
            label = new JLabel("...");
            add(label);

            service.schedule(new CounterWorker(), 1, TimeUnit.SECONDS);
        }

        public class CounterWorker extends SwingWorker<Integer, Integer> {

            @Override
            protected Integer doInBackground() throws Exception {
                System.out.println("Tick");
                for (int index = 0; index < 100; index++) {
                    count++;
                    publish(count);
                    Thread.yield();
                }
                return count;
            }

            @Override
            protected void process(List<Integer> chunks) {
                label.setText(Integer.toString(chunks.get(chunks.size() - 1)));
            }

            @Override
            protected void done() {
                service.schedule(new CounterWorker(), 1, TimeUnit.SECONDS);
            }

        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM