Java:无法等待/通知正常工作 - 并发问题

时间:2011-04-07 18:58:47

标签: java concurrency

自从我不得不处理Java中的并发编程(实际上是并发编程大学课程)以来,已经有很长一段时间了,而且我有一些看似非常基本的问题。下面的示例代码可能看起来有点奇怪,因为我没有使用标准JDK进行UI控件,但它是这样的:

//class Screen
public class Screen{
    private Frame rootContainer;

    public Screen(Frame rootContainer){
        this.rootContainer = rootContainer;
        this.createGui();
    }

    private void createGui(){
        Button btn = new Button("Call");
        btn.setBounds(20, 20, 100, 20);
        rootContainer.add(btn);
        btn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                ConcurrentDialog cr = createDialog();
                cr.start();
                //Suposedly only to be called after the Exit button in the dialog is clicked
                ((Button)e.getSource()).setLabel("Called");
                ((Button)e.getSource()).repaint();
            }
        });
    }

    private ConcurrentDialog createDialog(){
        return new ConcurrentDialog(rootContainer, this);
    }
}

//Class ConcurrentDialog
public class ConcurrentDialog extends Thread {
    private Frame rootContainer;
    private Screen screen;

    public ConcurrentDialog(Frame rootContainer, Screen screen){
        this.rootContainer = rootContainer;
        this.screen = screen;
    }

    public void run(){
        createDialog();
        synchronized(screen){
            try {
                screen.wait();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
    }

    private void createDialog(){
        Dialog dialog = new Dialog(rootContainer, true);
        dialog.setBounds(20, 20, 110, 35);
        Button btn = new Button("Exit");
        btn.setBounds(5, 5, 100, 20);

        btn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Button source = (Button)e.getSource();
                Dialog dialog = (Dialog)source.getParent();

                synchronized(screen){
                    screen.notify();
                }

                dialog.dispose();
                dialog.getOwner().remove(dialog);
                dialog = null;
            }
        });

        dialog.add(btn);
        dialog.show();
    }
}

在有人问之前,是的,我正在尝试实现一个模态对话框(事实上,我应该将ConcurrentDialog重命名为ModalDialog)。正如我之前所说,我不使用swing(因为我不能......嵌入式VM通常是特定于平台的UI,这是我的情况)并且这个特定的库没有本机模态对话框(意思是没有JOptionPane.showMessageDialog爱我)所以我从头开始构建一个。

无论如何,问题在于:似乎wait()方法的执行时间晚于((Button)e.getSource())。setLabel(“Called”)。我找到的解决方法是将btn设置为具有公共访问权限的全局属性,并将run()方法重构为:

public void run(){
    createDialog();
    synchronized(screen){
        try {
            screen.wait();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
    }
    screen.getBtn().setLabel("Called");
    screen.getBtn().repaint();
}

它以这种方式工作,但在我的“真实世界”场景中,这种实现在耦合方面会造成相当大的混乱。有什么指针吗?

2 个答案:

答案 0 :(得分:1)

你的cr.start()会立即返回。

你想要的是把等待(屏幕)放在cr.start()之后,并从run()方法中删除wait(screen)。

这样线程就会显示一个对话框并退出。关闭对话框后,将通知屏幕,并且您的createGui()。actionPerformed()将被唤醒。

答案 1 :(得分:0)

你不能使用swing / awt的多个线程,你不能在运行gui的线程上“等待”,否则它将停止工作。进行涉及gui的异步工作的方法是生成一个单独的线程(就像你正在做的那样),然后让它在需要“更新”gui时使用SwingUtilities.invokeLater()。