Core Java中每当创建一个窗口的时候都会在外面写这么一个东西,比如:import java.awt.*;
import javax.swing.*;public class Test 
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame();
frame.setSize(400, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}书上貌似也没有说为什么,只是说这样写会更安全,我不是很明白它的意思,谁能具体讲讲为什么?不加EventQueue.invokeLater行吗?

解决方案 »

  1.   

    http://zhidao.baidu.com/question/161013053.html?push=ql
      

  2.   

    为什么我感觉加不加效果一样呢?
    参考下面的一段代码,随便连接一个无法连接到的主机,在程序发出连接超时错误之前,整个程序都是死掉的,因此可以看出,即使加了EventQueue.invokeLater之后,这个程序依旧是单线程的,不相信大家对着下面的程序试试。import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    import java.net.*;@SuppressWarnings("serial")
    public class Talk extends JFrame
    {
    private ServerSocket server;
    private Socket[] sockets;
    private static final int MAX_LINK = 10;

    public Talk() throws IOException 
    {
    server = new ServerSocket(1680);
    sockets = new Socket[MAX_LINK];
    new ListenThread().start();

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Menu");
    menuBar.add(menu);
    JMenuItem newItem = new JMenuItem("New Connection");
    JMenuItem exitItem = new JMenuItem("Exit");
    menu.add(newItem);
    menu.addSeparator();
    menu.add(exitItem);

    setJMenuBar(menuBar);

    newItem.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent event)
    {
    final String ip = JOptionPane.showInputDialog(Talk.this, "Please input a IP address: ");
    if (ip == null || ip.equals(""))
    return;

    /*
     * 就是下面的这段代码,虽然看上去像多线程,但事实上整个程序依旧是单线程的,为什么会这样呢?
     */
    EventQueue.invokeLater(new Runnable()
    {
    public void run()
    {
    try
    {
    Socket socket = new Socket();
    socket.connect(new InetSocketAddress(ip, 1680), 10000);
    JFrame frame = new TalkFrame(socket);
    frame.setVisible(true);
    }
    catch (SocketTimeoutException e)
    {
    JOptionPane.showMessageDialog(Talk.this, "connect timeout");
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }

    }
    });
    }
    });
    exitItem.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent event)
    {
    System.exit(0);
    }
    });
    }

    public static void main(String[] args)
    {
    EventQueue.invokeLater(new Runnable()
    {
    public void run()
    {
    try
    {
    JFrame frame = new Talk();
    frame.setSize(400, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    });
    }

    private class ListenThread extends Thread
    {
    public void run()
    {
    while (true)
    {
    for (int i = 0; i < MAX_LINK; i++)
    {
    try
    {
    sockets[i] = server.accept();
    JFrame frame = new TalkFrame(sockets[i]);
    frame.setVisible(true);

    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    }
    }
    }

    private class TalkFrame extends JFrame
    {
    private JTextArea record = new JTextArea(10, 30);
    private JTextField message = new JTextField(20);
    private JButton button = new JButton("Send");
    private PipedWriter pipeOut;
    private PipedReader pipeIn;

    public TalkFrame(Socket socket) throws IOException
    {
    pipeOut = new PipedWriter();
    pipeIn = new PipedReader(pipeOut);
    String ip = socket.getInetAddress().getHostAddress();
    setTitle("Talk with " + ip);
    setLayout(new BorderLayout());

    add(new JLabel("Talk Record: "), BorderLayout.NORTH);
    add(new JScrollPane(record), BorderLayout.CENTER);
    record.setEditable(false);

    JPanel panel = new JPanel();
    panel.add(new JLabel("Message: "));
    panel.add(message);
    panel.add(button);
    add(panel, BorderLayout.SOUTH);

    button.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent event)
    {
    PrintWriter out = new PrintWriter(pipeOut);
    out.println(message.getText());
    record.append("I: " + message.getText() + "\n");
    message.setText("");
    }
    });
    addWindowListener(new WindowAdapter()
    {
    public void windowClosing(WindowEvent event)
    {
    setVisible(false);
    record.setText("");
    }
    });
    new WriteThread(pipeIn, new PrintWriter(socket.getOutputStream())).start();
    new ReadThread(this, ip, record, new BufferedReader(new InputStreamReader(socket.getInputStream()))).start();
    setSize(400, 300);
    setLocationByPlatform(true);
    setVisible(true);
    }
    } private class WriteThread extends Thread
    {
    private PrintWriter out;
    private BufferedReader in;

    public WriteThread(PipedReader pipeIn, PrintWriter out)
    {
    this.out = out;
    this.in = new BufferedReader(pipeIn);
    }

    public void run()
    {
    while (true)
    {
    try
    {
    while (true)
    {
    String s = in.readLine();
    out.println(s);
    out.flush();
    }
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    }
    }

    private class ReadThread extends Thread
    {
    private BufferedReader in;
    private JTextArea record;
    private String ip;
    private JFrame frame;

    public ReadThread(JFrame frame, String ip, JTextArea record, BufferedReader in)
    {
    this.frame = frame;
    this.ip = ip;
    this.in = in;
    this.record = record;
    }

    public void run()
    {
    while (true)
    {
    try
    {
    record.append(ip + ": " + in.readLine() + "\n");
    frame.setVisible(true);
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    }
    }
    }
      

  3.   

    我今天也遇见了这个问题,从网上找了一下答案。其中有一个答案是这样的:
    Java's GUI is strictly single-threaded.
    All GUI related things in java should always go through a single thread. The thread is our legendary "AWT-EventQueue-0"   . Hence all GUI related actions should necessarily go through the AWT Event thread. If not so you may end up in a deadlock. For small programs, this might never happen. But for a huge java application if you try frame.setVisible(true) kind of thing in main thread, you will soon find yourself searching a new job. What invokeLater() does is to post your Runnable in the AWT thread's event queue. So the code in your run method will be executed in the AWT-Eventqueue thread.
    大意是说,java的GUI都是的单线程,应该使用事件调度线程去执行,如果没意思使用事件调度线程的话,可能造成死锁。但是在小的程序中,这种现象(死锁)不会发生的;大的应用程序中才会出现这种现象!