Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heartbeat in Java: timerTask or thread.sleep()?

I want to implement a very simple client to server heartbeat in java. The most simple approach seems to be through sleep. Consider the metacode below.

class MyClass

    Thread heartbeatThread = new Thread();

    public void() startHeartBeat{
         Thread.sleep(4000);
         sock.write("H");
      }

Is this an adequate solution, or are there pitfalls I'm not considering?

I've also considered using the java.util.Timer.scheduleAtFixedRate approach. Would this be more robust/reliable? If so, why? Here's an example (it's not as clean IMO):

class HeartBeat
{
    Timer timer=new Timer();

    public void scheduleHeartBeat(int delay, int period) {
       timer.scheduleAtFixedRate( new HeartBeatTask(), delay, period);     
       }
}   

class HeartBeatTaskextends TimerTask {
     public void run() {
     sock.write("H");     
}

Will the second approach be granted higher priority?

like image 350
Adam Hughes Avatar asked Mar 09 '16 14:03

Adam Hughes


1 Answers

Firstly, your Thread-based idiom will not schedule at fixed rate without an infinite loop.

That's one disadvantage too: you probably want to set some condition to exit the loop.

You also need to catch InterruptedException when invoking static Thread.sleep.

Another popular idiom for scheduled execution is by using a ScheduledExecutorService.


Find the 3 alternatives below:

Timer

// says "foo" every half second
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        System.out.println("foo");
    }
}, 0, 500);
  • Pros: simple
  • Cons:

In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up."

Docs here.


Infinite loop

new Thread() {
    @Override
    public void run() {
        while (true) {
            // Says "blah" every half second
            System.out.println("blah");
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                // nope
            }
        }
    }
}.start();
  • Pros: super simple. You can vary your recurring delay programmatically.
  • Cons: Thread.sleep is still

subject to the precision and accuracy of system timers and schedulers. ... and requires catching InterruptedException.

Docs here.

Also:

  • your infinite loop might require a (somehow potentially cumbersome) breaking condition
  • no initial delay setting unless applied manually before infinite loop, which would require another try / catch.

Executors

ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor();
es.scheduleAtFixedRate(
    new Runnable() {
        @Override
        public void run() {
            // Says "bar" every half second
            System.out.println("bar");
        }
    }, 
    0, 500, TimeUnit.MILLISECONDS);
  • Pros: this is the most recent feature of the 3. Very simple and elegant - you can also schedule Callables (not at fixed rate though) and re-use the ExecutorService. The documentation for java.util.Timer actually mentions ScheduledThreadPoolExecutor (implementing the ScheduledExecutorService interface) as a "more versatile replacement for the Timer/TimerTask combination".
  • Cons as documented:

If any execution of this task takes longer than its period, then subsequent executions may start late,

Docs here.

like image 186
Mena Avatar answered Sep 21 '22 19:09

Mena