How to Pause and Resume a Thread in Java from another Thread

Solution 1:

You can't definitively pause one thread from another in the way you seem to want.

What you need to do instead, is signal that the other thread should stop, by setting some sort of flag. The thread in question must have logic to check this flag and pause its work when that happens.

So in this particular case, perhaps change MyThread as follows:

class MyThread extends Thread {

    private volatile boolean running = true; // Run unless told to pause

    ...

    @Override
    public void run()
    {
        for(int i=0 ; ; i++)
        {
            // Only keep painting while "running" is true
            // This is a crude implementation of pausing the thread
            while (!running)
                yield;

            area.setText(i+"");
    }

    public void pauseThread() throws InterruptedException
    {
        running = false;
    }

    public void resumeThread()
    {
        running = true;
    }

}

This is a crude example that for brevity uses a sort of spinlock rather than proper monitor-based sleeping. Hopefully though it communicates the idea of how you use a flag to control the pausing of the thread.

Note that if you were doing some long-running set of steps within the block, instead of just the setText call, it would be good practice to check Thread.currentThread().interrupted() between each of the steps - and exit the loop if the itnerrupt flag is set. This is broadly what the built-in blocking methods (e.g. I/O) do so that they can be interrupted by other threads - since the running flag is only checked one per loop, it doesn't do much good to set it if each loop takes 20 minutes.

Solution 2:

Try it like this:

class MyThread extends Thread {
    JTextArea area;
    private final Object GUI_INITIALIZATION_MONITOR = new Object();
    private boolean pauseThreadFlag = false;

    public MyThread(JTextArea area) {
        super();
        this.area = area;
    }

    @Override
    public void run() {
        for(int i=0 ; ; i++) {
            checkForPaused();
            area.setText(i+"");
        }
    }

    private void checkForPaused() {
        synchronized (GUI_INITIALIZATION_MONITOR) {
            while (pauseThreadFlag) {
                try {
                    GUI_INITIALIZATION_MONITOR.wait();
                } catch (Exception e) {}
            }
        }
    }

    public void pauseThread() throws InterruptedException {
        pauseThreadFlag = true;
    }

    public void resumeThread() {
        synchronized(GUI_INITIALIZATION_MONITOR) {
            pauseThreadFlag = false;
            GUI_INITIALIZATION_MONITOR.notify();
        }
    }
}

It is a good idead to use monitors like you did. But you can not force the wait from outside. You have to tell the thread to wait, until you notify him again (over the monitor). In this case, you just have this simple method checkForPaused() that you will have to put in strategic positions so there is not a long delay until the thread is paused.

You can also extend this function so you can ask the thread if he is paused with a flag set in checkForPaused() and a public boolean isPausing().