Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it so hard to stop a thread in Java?

I've come again in one of THOSE situations where it is just impossible to stop/destroy/suspend a thread. .interrupt() doesn't do the trick and .stop() and .suspend() are deprecated.

Very simple example:

public class TimerThread extends Thread {

    private JPanel colorPanel;

    public TimerThread(JPanel colorPanel) {
        this.colorPanel = colorPanel;
    }

    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
                colorPanel.repaint();
            } catch (Exception ex) {
                //do Nothing
            }
        }
    }
}

What this does is repaint a certain JPanel every second to change its colour. I want to start and stop the thread like this from another class:

timer = new Thread(new TimerThread(colorPanel));

    startButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            timer.start();
        }
    });

    stopButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            timer.interrupt();
        }
    });

Obviously (?) this doesn't work... I know I could use a Timer, a SwingWorker or declare the timer as timer = new TimerThread(colorPanel); and use a boolean instead of "true" in the run method, but I've been asked to declare timer as a "Thread" and nothing else.

To my surprise (or is this that stupid?), even this didn't work:

startButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            timer = new Thread(new TimerThread(colorPanel));
            timer.start();
        }
    });

    stopButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            timer.interrupt();
            timer = null;
        }
    });

So my question is simple: How do you make threads Start/Pause/Resume/Stop in Java?

like image 285
Matthias Avatar asked Feb 07 '26 15:02

Matthias


1 Answers

when you get an interrupt you should start the cleanup and return a.s.a.p. (or at the very least reset the interrupted status)

while (true) {
    try {
        Thread.sleep(1000);
        colorPanel.repaint();
    } catch(InterruptedException e){//from sleep
        return;//i.e. stop
    } catch (Exception ex) {
        //do Nothing
    }
}

another way is to check Thread.interrupted() in the condition (but you'll need to reset the interrupted status in the catch of InterruptedException

however in swing you can use javax.swing.Timer to let an event run every so often and stop that with the api of that

javax.swing.Timer timer = new Timer(1000,new ActionListener() {
     public void actionPerformed(ActionEvent e) {
         colorPanel.repaint();
     }
});
timer.setRepeats(true);

startButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        timer.start();
    }
});

stopButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        timer.stop();
    }
});
like image 143
ratchet freak Avatar answered Feb 09 '26 05:02

ratchet freak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!