简体   繁体   中英

Writing a comfortable pause/stop method for a Thread

For a Thread subclass in Java I was trying to write a method checkPauseAndStop() , whose purpose was to be nice one-liner I could periodically call within the run() method to check whether there are pause/stop requests and to act accordingly.

While fully functional, stopping the thread is handled via InterruptedException which forces the run()-code to be in a try-catch and feels error-prone
(as eg Thread.sleep() won't tell you anymore that it may throw such an Exception).

Is there any nice way that handles stopping the thread internally in the method without impeding on the run()-method?

Code sample:

public class SuspendableThread extends Thread
{
   private Semaphore lock = new Semaphore(1);
   public void checkPauseRequest() throws InterruptedException
    {
        if (isInterrupted())
            throw new InterruptedException();

        lock.acquire();
        lock.release();

    }

    @Override
    public void run()
    {
        try
        {
            while (true)
            {
                // Do_stuff
                checkPauseRequest();
            }

        }
        catch (InterruptedException e)
        {
            return;
        }
    }

Of cause, in this particular example, it isnt' necessary at all. For greater effect, imagine we'd have 50 or more consecutive blocks of

// Do_stuff
checkPauseRequest();

instead of just one.

If you want to catch an interrupt sent to a thread, to perform a cleanup for eg., you cannot get around putting your whole run() code block in a try/catch exception block. The reason being that if your thread is performing any kind of inter-thread signalling, via a conditional variable or a semaphore for eg (Calling the wait() method), your run() code block will immediately throw an InterruptedException , if the interrupt status flag is set for the thread. However, if you want to proactively check the interrupt status of your thread, the easiest way to do that would be to spray a bunch of interrupt points, aka your checkPause() method, and put a sleep of few nano seconds (Your sleep() method will throw an InterruptedException if the interrupted flag is set). This achieve your goals without compromising too much on the thread performance.

I would architect this using a ScheduledExecutorService (which you can create with Executors.newSingleThreadScheduledExecutor ) and an enum RunningState { RUNNING, PAUSED, STOPPED } .

While the state is RUNNING , we keep scheduling delayed tasks (using ScheduledExecutorService.schedule ). Each task checks to see if we are still RUNNING , and if so, enqueues a single loop iteration (using ExecutorService.submit or Executor.execute ). Then it schedules a new delayed task for the next iteration (not unlike a Timer , which you could potentially use instead, at the expense of yet another thread).

If the state is PAUSED , we keep scheduling the delayed tasks to keep checking for the transition back into RUNNING state. But we don't schedule the work items for the actual loop iterations.

If the state is STOPPED then we stop scheduling any more delayed tasks.

The state variable can be stored in a simple volatile field, which could be static (if there is only one of these things) or could be wrapped up in an object which represents the "thread" (which isn't actually a single thread anymore, but can resemble one from the caller's perspective).

Please make sure that what you're trying to achieve really makes sense and doesn't fall into let's reinvent the wheel category. Making any general one-size-fits-all stop method isn't something trivial, although it looked so even to Java creators. That's why Thread.stop() method is deprecated. ( https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.html#stop() ) (And Thread.destroy() wasn't actually implemented AFAICT.)

There's a very nice explanation available: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM