0

I have a periodic action which I want to do in a defined intervall (granularity in seconds). So I used a thread which sleeps for the requested time and then do the action and then sleep again and so on..

  public class DiscoveryThread extends Thread
  {
    private int deviceDiscoveryIntervall = 1;

    public void setDeviceDiscoveryIntervall(int seconds)
    {
       deviceDiscoveryIntervall = seconds;
    }

    @Override
    public void run()
    {
      while(!isInterrupted())
      {
        //do there the action

        try 
        {
          sleep(deviceDiscoveryIntervall*1000);
        } 
        catch (InterruptedException e) 
        {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

    }
  }

Now I want to set sometimes a new intervall for the periodic action. If the intervall was before 10 seconds and I set it 5 seconds after the last action to one second, I have to wait anyway 5 seconds until the next action, but It should do the action in this case immediately.

So how should I do this? If I use the interrupted() method, the sleep method will throw an InterruptedException and I could do the action immediately. But then I have to use an own flag for the whole loop as I don't want to exit the thread. And how is about calling the sleep() method again after an InterruptedException, is the interrupted flag still set? Am I able to interrupt the sleep() method again? And how about using the interrupted() method for not stopping the thread, is this not kind of missusing it?

Semaphor
  • 900
  • 2
  • 12
  • 33
  • Instead of blindly sleeping for a given number of seconds, it would be better to check the actual clock time at the start of the loop. If it's time to perform the action, then perform it. Otherwise, calculate how long until it will be time to perform it, and then sleep for that amount of time. If the sleep returns early because of an interrupt, no problem: It'll just sleep again. (That is, assuming an interrupt doesn't _mean_ something.) – Solomon Slow Nov 12 '15 at 16:04
  • That would be also a solution, if I sleep always for one second and check after every loop if I have to do the action or if I have to sleep one more second. – Semaphor Nov 13 '15 at 07:06

2 Answers2

2

The thread should wait on an object with the correct timeout, call notifyAll on the object when you want the thread to wake up early.

You should consider using a ScheduledExecutorService for anything like this though rather than trying to roll your own.

Tim B
  • 40,716
  • 16
  • 83
  • 128
1

Use a ScheduledExecutorService:

private final Runnable r = new Runnable() {
    @Override
    public void run() {
        // ...
    }
};

private final ScheduledExecutorService ses = 
    Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> sf = ses.scheduleAtFixedRate(r, 0, 10, TimeUnit.SECONDS);

// change to 5 sec: cancel and reschedule
sf.cancel();
sf = ses.scheduleAtFixedRate(r, 0, 5, TimeUnit.SECONDS);
Jean Logeart
  • 52,687
  • 11
  • 83
  • 118