0

This is about java's built-in Timer-class. I need a method to be invoked frequently at certain set intervals, but if the execution takes too long, I don't want them to pile up, so the solution would be to queue up the next execution at the beginning of said method. Of course this means that the queueing happens in the same queue Thread. Would this work out or would this cause problems?

public class SomeClass extends TimerTask {
   public static SomeClass timer;
   public void run() {
      timer.schedule(this,100);
      //do stuff
   }

}
Zain
  • 95
  • 1
  • 8

1 Answers1

1

Java has the executor services to do exactly what you want to do. Have a look at the method ScheduledExecutorService#scheduleWithFixedDelay(). As opposed to the method ScheduledExecutorService#scheduleAtFixedRate(), the method with fixed delay does not try to keep up.

Here is an example:

public void run() {
    Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(
            this::task, 0, 10, TimeUnit.MILLISECONDS);
}

public void task() {
    // run your task
}

Indeed, your use case seems to be not covered by the standard library methods. However, you should be able to use the following class to do what you want.

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

public class TimerExample {
    private final ScheduledExecutorService executor = Executors
            .newSingleThreadScheduledExecutor();
    private final Runnable task;
    private final Consumer<Exception> onException;
    private final long delay;
    private final TimeUnit unit;

    public TimerExample(Runnable task, Consumer<Exception> onException,
            long delay, TimeUnit unit) {
        this.task = task;
        this.onException = onException;
        this.delay = delay;
        this.unit = unit;
    }

    public void start() {
        executor.execute(this::execute);
    }

    private void execute() {
        executor.schedule(this::execute, delay, unit);
        try {
            task.run();
        } catch (Exception e) {
            onException.accept(e);
        }
    }
}

And here the usage:

    new TimerExample(() -> System.out.println("."),
            Exception::printStackTrace, 20, TimeUnit.MILLISECONDS).start();

Since it uses a single threaded executor service, it will not start the next execution until the previous is finished. Also, it schedules the next execution before the task itself is executed.

Also, see this SO-question about why you should prefer the executor services above the Timer class.

You still have to implement the shutdown mechanism by yourself.

Community
  • 1
  • 1
Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
  • Whilst scheduleWithFixedDelay() starts the timer for the next execution only after the previous one finished, scheduleAtFixedRate() bunches up. What I am searching for ist a method that bunches up only once, so that if one execution takes too long (say tne times too long), the next one starts immediately after, but the one after that gets triggered after the specified delay as if nothing happened. *Example:* Delay: 200 ms execution[took:10ms. Started: 0ms] -> execution[took:1000 ms. Started: 200ms] -> execution[took:10 ms. Started: 1200ms] -> execution[took:30ms. Started: 1400ms] – Zain Feb 14 '16 at 12:15
  • In the mean time I wrote a class myself, if anyone wants to see it it should be completely safe: http://pastebin.com/raw/jcUrtwC5 :) My use case is a live simulation that uses timesteps. By the way you are using C syntax ;) – Zain Feb 14 '16 at 17:31
  • Thank you very much for your answer, executor.schedule seems to be able to handle something the Timer class can't handle, wich is queing up the same thing twice. I think? – Zain Feb 14 '16 at 17:49
  • Good thing you found a solution. However, the syntax is correct Java 8 syntax, which does support lambdas. – Stefan Dollase Feb 14 '16 at 18:00
  • I'm so sorry looks like my compiler is just not up to date then :o It really looked like c++ syntax – Zain Feb 15 '16 at 13:39