本帖最后由 dz007 于 2009-09-18 22:35:19 编辑

解决方案 »

  1.   

    你弄混掉了。界面是在EDT里面的,而你的那个actionPerformed是运行在AWT-Event里面的。也就是EDT要D的那些进程。界面和响应事件分离是基本的原则。所谓的EDT阻塞是指,Event Queue被你这个actionPerformed阻塞了,没法在接收其他Event事件。也就是你原来的那个窗口没法被其他事件触发了希望我说明白了
      

  2.   

    EDT线程被阻塞这种说法就不太好,容易有误解。
    实际情况不太好说清楚,你在调试环境下设个断点,看看java调用堆栈就知道是怎么回事儿了。
      

  3.   

    EDT线程有一个存放触发事件的队列,用来异步处理触发事件,这些事件依次通过AWT-Event线程更新界面这时的主线程还是可以通过AWT-Event线程更新界面是这样理解吧……
      

  4.   

    简单的说EDT和UDT线程没有被阻塞,而是在UDT线程里(showDialog方法中)启动了一个新的Event Dispatcher,所有的AWT/Swing Event都会被处理(当然会屏蔽一些对话框下面的窗口事件),直到对话框退出,才返回原来的actinoPerformed方法。
      

  5.   

    调试看线程堆栈不会吗?
    JDK下的src.zip就是最好的资料。
      

  6.   

    就只看到了一条EDT,就是AWT-EventQueue-0 而且一直都是运行状态…………
      

  7.   


    Event Dispatcher就是一直等着有Event就处理,处理完了就再等。
    在你的Frame窗口上的某个EventListerner的代码里设个断点。
    程序中断了才能看到调用堆栈啊。
      

  8.   

    我看到堆栈了,还是只有一个EDT………………
      

  9.   


    http://java.sun.com/docs/books/tutorial
    就是很好的入门教程。对于Java技术,SDN是一个比CSDN好很多的社区
      

  10.   

    Eclipse吗?Netbeans没用过。只有一个EDT是什么意思?没有主进程?那你的那个每秒写个数字怎么做的?没有看到EDT的队列?如果是Eclipse的话,如果你是在
    String result = JOptionPane.showInputDialog...这句这里设的断点,应该左边会有个加号,点开。
      

  11.   

    没有,线程有很多,但事件分派线程只有一条actionPerformed中的内容是交给事件分派线程执行的,JOptionPane.showInputDialog会造成调用线程阻塞,而现在结果是唯一的一条EDT是running状态,并且InputDialog也是正常运行的,这点很费解啊……
      

  12.   

    关于Swing的线程问题,你看看这两篇文章吧,1998年写的,很经典,基本就是Swing设计时的核心思想了:http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html和http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html如果再不明白,你把源代码发上来看看。我实在不理解你说的那个,理论上不可能的
      

  13.   

    唉~我还是把我的悲剧代码贴上来吧…………
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;public class SwingTest extends javax.swing.JFrame implements ActionListener {
    private JPanel jPanel1;
    private JButton jButton1;
    private static JTextField jTextField1;
    private JButton jButton2;
    private JPanel jPanel3;
    private JPanel jPanel2;
    private static SwingTest inst;
    private static int i; /**
     * Auto-generated main method to display this JFrame
     */
    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
    public void run() {
    inst = new SwingTest();
    inst.setLocationRelativeTo(null);
    inst.setVisible(true);
    }
    });
    for (i = 0; i < 100; i++) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    SwingUtilities.invokeLater(new Runnable() {
    public void run() {
    jTextField1.setText(jTextField1.getText() + i + " ");
    }
    });
    }
    } public SwingTest() {
    super();
    initGUI();
    } private void initGUI() {
    try {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    {
    jPanel1 = new JPanel();
    BorderLayout jPanel1Layout = new BorderLayout();
    jPanel1.setLayout(jPanel1Layout);
    getContentPane().add(jPanel1, BorderLayout.CENTER);
    {
    jPanel2 = new JPanel();
    CardLayout jPanel2Layout = new CardLayout();
    jPanel2.setLayout(jPanel2Layout);
    jPanel1.add(jPanel2, BorderLayout.NORTH);
    jPanel2.setPreferredSize(new java.awt.Dimension(392, 120));
    {
    jTextField1 = new JTextField();
    jPanel2.add(jTextField1, "jTextField1");
    jTextField1.setText("");
    } }
    {
    jPanel3 = new JPanel();
    jPanel1.add(jPanel3, BorderLayout.CENTER);
    {
    jButton1 = new JButton();
    jButton1.setText("jButton1");
    jPanel3.add(jButton1);
    jButton1.addActionListener(this); }
    }
    }
    pack();
    } catch (Exception e) {
    e.printStackTrace();
    }
    } @Override
    public void actionPerformed(ActionEvent arg0) {
    String result = JOptionPane.showInputDialog(this, "请输入联系人ID:", "添加联系人",
    JOptionPane.INFORMATION_MESSAGE);
    System.out.println(result);
    System.out.println(result);
    }
    }
      

  14.   

    看来我也有收获了,JOptionPane.showInputDialog的过程是不会阻塞进程的。如果你想阻塞的话,可以这样做实验:@Override
        public void actionPerformed(ActionEvent arg0) {
            Thread.sleep(50000);
            String result = JOptionPane.showInputDialog(this, "请输入联系人ID:", "添加联系人",
                    JOptionPane.INFORMATION_MESSAGE);
            System.out.println(result);
            System.out.println(result);
        }
    关于你说看不到Event-Queue,肯定是你设置不对,你把断点放在String result= 这一句,然后点一下按钮,肯定能看到一堆Event-Queue的,你再看看另外,for (i = 0; i < 100; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        jTextField1.setText(jTextField1.getText() + i + " ");
                    }
                });
            }你怎么能这样用呢?两个i不是同步的,打印在jTextField1肯定不会一直是从0到100。
      

  15.   

    JOptionPane.showInputDialog不阻塞EDT看来知道的人不多,Sun的API documentation里面1.6把这句描诉改了,由current thread给为calling thread,你对比一下1.6和1.5文档就可以发现,以下是一篇讨论这个的文章http://www.coderanch.com/t/344616/Swing-AWT-SWT-JFace/java/JOptionPane-thread-safe
      

  16.   

    我现在搞不懂的是String result = JOptionPane.showInputDialog 要等待返回值的,这个语句是在哪执行的呢
      

  17.   

    刚看了一篇文章,说是模态对话框会接替派发线程的工作,直到销毁
    好像也是一种猜测而已,不知是否正确http://daniel-wuz.javaeye.com/blog/135445
      

  18.   


    无语,有src自己看看不就好了吗?那文章是正确的这样看src,showInputDialog里面有这行,JDialog dialog = pane.createDialog(parentComponent, title, style);创建了一个JDialog,public class JDialog extends Dialog,所以去看public class Dialog extends Window,在showInputDialog里面调用了show(),那我们去看show(),下面是代码,public void show() {
            beforeFirstShow = false;
            if (!isModal()) {
                conditionalShow(null, null);
            } else {
                // Set this variable before calling conditionalShow(). That
                // way, if the Dialog is hidden right after being shown, we
                // won't mistakenly block this thread.
                keepBlocking = true;            // Store the app context on which this dialog is being shown.
                // Event dispatch thread of this app context will be sleeping until
                // we wake it by any event from hideAndDisposeHandler().
                showAppContext = AppContext.getAppContext();            AtomicLong time = new AtomicLong();
                Component predictedFocusOwner = null;
                try {
                    predictedFocusOwner = getMostRecentFocusOwner();
                    if (conditionalShow(predictedFocusOwner, time)) {
                        // We have two mechanisms for blocking: 1. If we're on the
                        // EventDispatchThread, start a new event pump. 2. If we're
                        // on any other thread, call wait() on the treelock.                    modalFilter = ModalEventFilter.createFilterForDialog(this);                    final Runnable pumpEventsForFilter = new Runnable() {
                            public void run() {
                                EventDispatchThread dispatchThread =
                                    (EventDispatchThread)Thread.currentThread();
                                dispatchThread.pumpEventsForFilter(new Conditional() {
                                    public boolean evaluate() {
                                        return keepBlocking && windowClosingException == null;
                                    }
                                }, modalFilter);
                            }
                        };                    // if this dialog is toolkit-modal, the filter should be added
                        // to all EDTs (for all AppContexts)
                        if (modalityType == ModalityType.TOOLKIT_MODAL) {
                            Iterator it = AppContext.getAppContexts().iterator();
                            while (it.hasNext()) {
                                AppContext appContext = (AppContext)it.next();
                                if (appContext == showAppContext) {
                                    continue;
                                }
                                EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
                                // it may occur that EDT for appContext hasn't been started yet, so
                                // we post an empty invocation event to trigger EDT initialization
                                Runnable createEDT = new Runnable() {
                                    public void run() {};
                                };
                                eventQueue.postEvent(new InvocationEvent(this, createEDT));
                                EventDispatchThread edt = eventQueue.getDispatchThread();
                                edt.addEventFilter(modalFilter);
                            }
                        }                    modalityPushed();
                        try {
                            if (EventQueue.isDispatchThread()) {
                                /*
                                 * dispose SequencedEvent we are dispatching on current
                                 * AppContext, to prevent us from hang.
                                 *
                                 */
                                // BugId 4531693 ([email protected])
                                SequencedEvent currentSequencedEvent = KeyboardFocusManager.
                                    getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
                                if (currentSequencedEvent != null) {
                                    currentSequencedEvent.dispose();
                                }                            /*
                                 * Event processing is done inside doPrivileged block so that
                                 * it wouldn't matter even if user code is on the stack 
                                 * Fix for BugId 6300270
                                 */                             AccessController.doPrivileged(new PrivilegedAction() {
                                         public Object run() {
                                            pumpEventsForFilter.run();
                                            return null;
                                         }
                                 });
                            } else {
                                synchronized (getTreeLock()) {
                                    Toolkit.getEventQueue().postEvent(new PeerEvent(this,
                                                                                    pumpEventsForFilter,
                                                                                    PeerEvent.PRIORITY_EVENT));
                                    while (keepBlocking && windowClosingException == null) {
                                        try {
                                            getTreeLock().wait();
                                        } catch (InterruptedException e) {
                                            break;
                                        }
                                    }
                                }
                            }
                        } finally {
                            modalityPopped();
                        }                    // if this dialog is toolkit-modal, its filter must be removed
                        // from all EDTs (for all AppContexts)
                        if (modalityType == ModalityType.TOOLKIT_MODAL) {
                            Iterator it = AppContext.getAppContexts().iterator();
                            while (it.hasNext()) {
                                AppContext appContext = (AppContext)it.next();
                                if (appContext == showAppContext) {
                                    continue;
                                }
                                EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
                                EventDispatchThread edt = eventQueue.getDispatchThread();
                                edt.removeEventFilter(modalFilter);
                            }
                        }                    if (windowClosingException != null) {
                            windowClosingException.fillInStackTrace();
                            throw windowClosingException;
                        }
                    }
                } finally {
                    if (predictedFocusOwner != null) {
                        // Restore normal key event dispatching
                        KeyboardFocusManager.getCurrentKeyboardFocusManager().
                            dequeueKeyEvents(time.get(), predictedFocusOwner);
                    }
                }
            }
        }
    应该很容易看懂了吧?
    里面的pumpEventsForFilter,你一直跟着,就能看到这个boolean pumpOneEventForFilters(int id) {
            try {
                AWTEvent event;
                boolean eventOK;
                do {
                    event = (id == ANY_EVENT)
                        ? theQueue.getNextEvent()
                        : theQueue.getNextEvent(id);                eventOK = true;
                    synchronized (eventFilters) {
                        for (int i = eventFilters.size() - 1; i >= 0; i--) {
                            EventFilter f = eventFilters.get(i);
                            EventFilter.FilterAction accept = f.acceptEvent(event);
                            if (accept == EventFilter.FilterAction.REJECT) {
                                eventOK = false;
                                break;
                            } else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {
                                break;
                            }
                        }
                    }
                    eventOK = eventOK && SunDragSourceContextPeer.checkEvent(event);
                    if (!eventOK) {
                        event.consume();
                    }
                }
                while (eventOK == false);
                          
                if (dbg.on) {
                    dbg.println("Dispatching: "+event);
                }            theQueue.dispatchEvent(event);
                return true;
            }
            catch (ThreadDeath death) {
                return false;        }
            catch (InterruptedException interruptedException) {
                return false; // AppContext.dispose() interrupts all
                              // Threads in the AppContext        }
            // Can get and throw only unchecked exceptions
            catch (RuntimeException e) {
                processException(e, modalFiltersCount > 0);
            } catch (Error e) {
                processException(e, modalFiltersCount > 0);
            }
            return true;
        }
      

  19.   

    让你看stack也不知道你都看到什么了。给你贴个stack的代码import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    public class EDTStack extends JFrame
    {
        class DLG extends JDialog
        {
            DLG()
            {
                super(EDTStack.this,"Dialog",true);
                JButton btn = new JButton("Dump Stack");
                btn.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        Thread.dumpStack();
                    }
                    
                });
                this.getContentPane().add(btn,BorderLayout.CENTER);
                setBounds(200,140,400,300);
            }
        }
        EDTStack()
        {
            super("Frame");
            JButton btn = new JButton("Show Dialog");
            btn.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    new DLG().setVisible(true);
                }
                
            });
            this.getContentPane().add(btn,BorderLayout.CENTER);
            setBounds(0,0,800,600);
        }
        public static void main(String[] args)
        {
             new EDTStack().setVisible(true);
        }}输出结果:
    java.lang.Exception: Stack trace
    at java.lang.Thread.dumpStack(Thread.java:1206)
    at EDTStack$DLG$1.actionPerformed(EDTStack.java:22)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6263)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6028)
    at java.awt.Container.processEvent(Container.java:2041)
    at java.awt.Component.dispatchEventImpl(Component.java:4630)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
    at java.awt.Container.dispatchEventImpl(Container.java:2085)
    at java.awt.Window.dispatchEventImpl(Window.java:2475)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
    at java.awt.Dialog$1.run(Dialog.java:1045)
    at java.awt.Dialog$3.run(Dialog.java:1097)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.awt.Dialog.show(Dialog.java:1095)
    at java.awt.Component.show(Component.java:1563)
    at java.awt.Component.setVisible(Component.java:1515)
    at java.awt.Window.setVisible(Window.java:841)
    at java.awt.Dialog.setVisible(Dialog.java:985)
    at EDTStack$1.actionPerformed(EDTStack.java:38)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6263)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6028)
    at java.awt.Container.processEvent(Container.java:2041)
    at java.awt.Component.dispatchEventImpl(Component.java:4630)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
    at java.awt.Container.dispatchEventImpl(Container.java:2085)
    at java.awt.Window.dispatchEventImpl(Window.java:2475)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
    有没有看到stack中有两段事件分派处理(dispatchEvent)?
      

  20.   

    原来的breakpoint加错地方了,加在启动dialog的按钮上……代码好像看懂些了,当EDT在生成dialog的时候,用替换的方式接管了EDT的任务