Java: не удается получить ожидание / уведомление для правильной работы - проблема параллелизма - PullRequest
0 голосов
/ 07 апреля 2011

Прошло много времени с тех пор, как мне приходилось иметь дело с параллельным программированием на Java (на самом деле это были занятия по параллельному программированию в колледже), и у меня возникла какая-то довольно простая проблема. Приведенный ниже пример кода может показаться странным, поскольку я не использую стандартный JDK для элементов управления пользовательского интерфейса, но выглядит так:

//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 (просто потому, что не могу ... Встраиваемые виртуальные машины обычно зависят от платформы, когда дело касается пользовательского интерфейса, и это мой случай), и эта конкретная библиотека не имеет собственного модального диалога. (что означает, что я не люблю 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 ]

1 голос
/ 07 апреля 2011

ваш cr.start () возвращается немедленно.

Вам нужно поставить wait (screen) вместо после cr.start () и удалить wait (screen) из метода run ().

Таким образом, поток будет отображатьсядиалог и выход.Как только диалоговое окно закроется, на экран будет выведено уведомление, и ваш createGui (). ActionPerformed () проснется.

0 голосов
/ 07 апреля 2011

вы не можете использовать несколько потоков с swing / awt, и вы не можете "ждать" в потоке, на котором запущен графический интерфейс, или он перестанет работать.способ выполнить асинхронную работу, которая включает в себя графический интерфейс пользователя, состоит в том, чтобы порождать отдельный поток (как вы делаете), а затем использовать этот поток, используя SwingUtilities.invokeLater () всякий раз, когда ему необходимо «обновить» графический интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...