Tony
Tony

Reputation: 3805

Wait() statement with Swing

I have 2 buttons. 1st starts thread, 2nd makes it wait. 1st button works fine, but second doesn't want to stop 1st button thread. What's wrong? How to make it stop?

package SwingExp;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class WhichButton implements ActionListener {

    JLabel jLab, testLab = new JLabel();
    JFrame jfrm = new JFrame("Button example");
    JButton firstButton = new JButton("First"), secondButton = new JButton("Second");

    WhichButton() {


        jfrm.setLayout(new FlowLayout());
        jfrm.setSize(220, 90);

        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        firstButton.addActionListener(this);
        secondButton.addActionListener(this);
        jfrm.add(firstButton);
        jfrm.add(secondButton);

        jLab = new JLabel("Press button");
        jfrm.add(jLab);
        jfrm.add(testLab);

        jfrm.setVisible(true);
    }

    class SimpleThread extends Thread {
        Thread t;
        boolean suspendFlag;

        SimpleThread() {
            t = new Thread(this, "settingThread");
            t.start();

        }

        public void run() {


            for (int i = 0; i <= 10; i++) {
                synchronized (this) {
                    while (suspendFlag) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                        }
                    }
                }

                testLab.setText(Integer.toString(i));

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }

            }

            firstButton.setEnabled(true);
            testLab.setText("Completed.");
        }

        synchronized void setSuspendFlag(boolean suspendFlag) {
            this.suspendFlag = suspendFlag;
        }


    }


    public void actionPerformed(ActionEvent e) {

        SimpleThread st = new SimpleThread();

        if (e.getActionCommand().equals("First")) {
            jLab.setText("First");
            firstButton.setEnabled(false);
            st.setSuspendFlag(false);

        } else {
            st.setSuspendFlag(true);
        }
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new WhichButton();
            }
        });
    }


}

I was trying to use interrupt() method, but it makes me one more thread or something like that.

Upvotes: 0

Views: 91

Answers (2)

user2511414
user2511414

Reputation:

First the suspend field should be volatile volatile boolean suspendFlag

and the second thing is you are synchronizing whole object, it means no any threads are allowed to use this object and its members, so simple synchronize on something else, like this

private Object _mutex=new Object();
public void run() {


    for (int i = 0; i <= 10; i++) {
        synchronized (_mutex) {
            while (suspendFlag) {
                try {
                    _mutex.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }

        testLab.setText(Integer.toString(i));

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {

        }

    }

    firstButton.setEnabled(true);
    testLab.setText("Completed.");
}

and the suspending thread would be like this

void setSuspendFlag(boolean suspendFlag) {
    this.suspendFlag = suspendFlag;
}

EDIT : also don't forget to notify about the resume the waited thread in action performed

public void actionPerformed(ActionEvent e) {

    //SimpleThread st = new SimpleThread(); //what is this for?

    if (e.getActionCommand().equals("First")) {
        jLab.setText("First");
        firstButton.setEnabled(false);
        st.setSuspendFlag(false);
        try{synchronized(_mutex){_mutex.notify();}}catch(Exception){}
    } else {
        st.setSuspendFlag(true);
    }
}

Upvotes: 2

jtahlborn
jtahlborn

Reputation: 53674

you need to notify() the sleeping thread in the setSuspendFlag() method. otherwise, the thread will block forever in the wait() call.

Also, every time your buttons are pressed, you are creating a new SimpleThread instance. you need to make the SimpleThread instance a member variable and only create it once.

Upvotes: 3

Related Questions