在 Java 中使用 wait()

Use wait() in Java

我需要在新线程中创建一个新的 JFrame。当我关闭 JFrame 时,我需要 return 一个字符串。 问题是 wait() 方法 "doesn't wait" new Thread 的 "notify()"。 谢谢你的回答。

import java.awt.Button;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class FinestraTesto extends Thread {

    JLabel jdescr;
    JTextArea testo;
    JPanel pannelloTasti;
    JButton bottoneInvio;
    JButton bottoneAnnulla;
    JFrame finestraTestuale;
    JPanel panAll;
    static Boolean pause = true;
    String titolo;
    String descrizione;
    private static String testoScritto = "";

    public String mostra() {
        // Create a new thread
        Thread th = new Thread(new FinestraTesto(titolo, descrizione));
        th.start();
        synchronized (th) {
                try {
                    // Waiting the end of th.
                    th.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }

        return testoScritto;
    }

    public void run() {
        synchronized (this) {
            System.out.println("Fatto 1 thread");
            finestraTestuale = new JFrame(titolo);
            finestraTestuale.setPreferredSize(new Dimension(600, 200));
            finestraTestuale.setSize(600, 200);
            Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
            finestraTestuale.setLocation(
                    dim.width / 2 - finestraTestuale.getSize().width / 2,
                    dim.height / 2 - finestraTestuale.getSize().height / 2);

            panAll = new JPanel();
            panAll.setLayout(new BoxLayout(panAll, BoxLayout.Y_AXIS));

            bottoneInvio = new JButton("Conferma");
            bottoneAnnulla = new JButton("Annulla");
            pannelloTasti = new JPanel();
            testo = new JTextArea();
            testo.setPreferredSize(new Dimension(550, 100));
            testo.setSize(550, 100);

            JScrollPane scrollPane = new JScrollPane();
            scrollPane.setViewportView(testo);

            jdescr = new JLabel(descrizione);
            jdescr.setPreferredSize(new Dimension(550, 50));
            jdescr.setSize(550, 50);

            pannelloTasti.setLayout(new BoxLayout(pannelloTasti,
                    BoxLayout.X_AXIS));
            pannelloTasti.add(bottoneInvio);
            pannelloTasti.add(bottoneAnnulla);

            panAll.add(jdescr);
            panAll.add(scrollPane);
            panAll.add(pannelloTasti);

            finestraTestuale.add(panAll);

            bottoneInvio.addActionListener(new ActionListener() {

                @Override
                /**
                 * metodo attivato quando c'è un'azione sul bottone
                 */
                public void actionPerformed(ActionEvent arg0) {
                    testoScritto = testo.getText();
                    pause = false;
                    finestraTestuale.show(false);
                    // send notify
                    notify();
                }
            });
            bottoneAnnulla.addActionListener(new ActionListener() {

                @Override
                /**
                 * metodo attivato quando c'è un'azione sul bottone
                 */
                public void actionPerformed(ActionEvent arg0) {
                    pause = false;
                    testoScritto = "";
                    finestraTestuale.show(false);
                    // send notify
                    notify();
                }
            });
            finestraTestuale.show();
        }
    }

    public FinestraTesto(String titolo, String descrizione) {
        this.titolo = titolo;
        this.descrizione = descrizione;
    }
}

您最好使用 Synchronizers 而不是 waitnotify。它们更受欢迎,因为简单和安全。

Given the difficulty of using wait and notify correctly, you should use the higher-level concurrency utilities instead.

Effective Java (2nd Edition), Item 69

我用这个 class 解决了:

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class CustomDialog
{
    private List<JComponent> components;

    private String title;
    private int messageType;
    private JRootPane rootPane;
    private String[] options;
    private int optionIndex;
    private JTextArea testo;
    public CustomDialog(String title,String descrizione)
    {
        components = new ArrayList<>();

        setTitle(title);
        setMessageType(JOptionPane.PLAIN_MESSAGE);
        addMessageText(descrizione);
        testo = new JTextArea();
        testo.setPreferredSize(new Dimension(550, 100));
        testo.setSize(550, 100);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewportView(testo);

        addComponent(scrollPane);
        setRootPane(null);
        setOptions(new String[] { "Send", "Cancel" });
        setOptionSelection(0);
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public void setMessageType(int messageType)
    {
        this.messageType = messageType;
    }

    public void addComponent(JComponent component)
    {
        components.add(component);
    }

    public void addMessageText(String messageText)
    {
        components.add(new JLabel(messageText));
    }

    public void setRootPane(JRootPane rootPane)
    {
        this.rootPane = rootPane;
    }

    public void setOptions(String[] options)
    {
        this.options = options;
    }

    public void setOptionSelection(int optionIndex)
    {
        this.optionIndex = optionIndex;
    }

    public String show()
    {
        int optionType = JOptionPane.OK_CANCEL_OPTION;
        Object optionSelection = null;

        if(options.length != 0)
        {
            optionSelection = options[optionIndex];
        }

        int selection = JOptionPane.showOptionDialog(rootPane,
                components.toArray(), title, optionType, messageType, null,
                options, optionSelection);

        if(selection == 0)
            return testo.getText();
        else
            return null;
    }
}