Swing Thread安全编程 [英] Swing Thread Safe Programming

查看:94
本文介绍了Swing Thread安全编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the dialog */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            MyDialog dialog = new MyDialog(new javax.swing.JFrame(), true);
            dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent e) {
                    System.exit(0);
                }
            });
            dialog.setVisible(true);
        }
    });
}

MyDialog类只有很少的组合和文本字段,并且正在使用DB值填充组合。在选择一个组合值时,我从DB获取另一个值以填充下一个组合。

The MyDialog class just has few combos and textfields and am populating combo with DB values. On selecting one combo value i fetch another value from DB to populate the next combo.

上述程序以相同的方式运行,而不使用invokeLater线程。什么时候invokeLater在Swing编程中变得有用。我已经阅读了一些关于它的内容,但似乎都是理论上的。 invokeLater对应用程序有何不同?仅仅在main方法中使用它还是应该在动作监听器中使用它?

The above program runs the same way without using invokeLater threading. When does invokeLater becomes useful in Swing programming. I have read some about it, but all seems to be theoratical. What difference does the invokeLater makes to the application? Is it enough to use it just inside main method or it should also be used in action Listeners?

SwingUtilities.invokeLater和java.awt.EventQueue.invokeLater - 它们是否相同?

SwingUtilities.invokeLater and java.awt.EventQueue.invokeLater - are they same?

推荐答案

没有什么理论上的。这很实用。 SwingUtilities.invokeLater()方法保证 Runnable 中的代码将在上运行事件派遣线程(EDT)。这很重要,因为Swing不是线程安全的,因此任何与GUI相关的东西( Swing 等)都需要在 EDT上运行 EDT 是只要它发生就会发生线程,它不保证执行事务的顺序。如果GUI代码在后台线程中执行(例如,在 SwingWorker 实例中),那么它可能会抛出错误。我学到了很多困难:在我学习的几年里,在后台线程中执行GUI更改代码导致了我无法理解的随机,不一致的 RuntimeException 。这是一个很好的学习经历( SwingWorker 有一个 doInBackground()方法用于后台任务和 done() EDT 任务的方法。

Nothing theoretical about it. It's very practical. The SwingUtilities.invokeLater() method guarantees that the code within the Runnable will run on the Event Dispatch Thread (EDT). This is important because Swing is not thread-safe, thus anything related to the GUI (Swing, etc.) needs to run on the EDT. The EDT is a "it happens whenever it happens" thread that makes no guarantees about the order in which things are executed. If the GUI code is executed within a background thread (say, within a SwingWorker instance), then it can throw errors. I learned this the hard way: in my learning years, executing GUI-changing code within a background thread caused random, inconsistent RuntimeExceptions that I couldn't figure out. It was a good learning experience (SwingWorker has a doInBackground() method for background tasks and a done() method for EDT tasks).

以同样的方式你不希望在后台线程上执行GUI代码,您也不想在 EDT 上执行大型操作(数据库查询等)。这是因为 EDT 正在调度所有GUI事件,所以 EDT 上的所有内容都应该非常简短和甜蜜。您可以通过将 JProgressBar 设置为不确定来轻松查看此内容。

In the same way you don't want to execute GUI code on a background thread, you also don't want to execute large operations (database queries, etc) on the EDT. This is because the EDT is dispatching all of the GUI events so everything on the EDT should be very short and sweet. You can easily see this with a JProgressBar set to indeterminate.

此SSCCE应该很好地说明它。注意 JProgressBar 的动作为方法()被调用,一次在后台线程上,一次在<$上c $ c> EDT thread。

This SSCCE should illustrate it nicely. Notice the motion of the JProgressBar as method() is called, once on a background thread and once on a EDT thread.

import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

/**
 *
 * @author Ryan
 */
public class Test {

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        JProgressBar jpb = new JProgressBar();
        jpb.setIndeterminate(true);
        frame.add(jpb);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        new Task().execute();
    }

    public static void method() { // This is a method that does a time-consuming task.
        for(int i = 1; i <= 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }

    static class Task extends SwingWorker<Void, Void> {

        @Override
        protected Void doInBackground() throws Exception {
            /* Executing method on background thread.
             * The loading bar should keep moving because, although method() is time consuming, we are on a background thread.
            */ 
            method();
            return null;
        }

        @Override
        protected void done() {
            /* Executing method on Event Dispatch Thread.
             * The loading bar should stop because method() is time consuming and everything on the Event Dispatch Thread
             * (like the motion of the progress bar) is waiting for it to finish.
            */

            // 
            method();
        }
    }
}

希望这有帮助。

这篇关于Swing Thread安全编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆