Search code examples
javalambdajava-8functional-programminggeneric-programming

How to invoke a generic function inside another function with a timeout with java 8?


I have a function that gives me a state of service:

public ServiceState getServiceState(){
      return someService().getState(); //currently state return "NOTACTIVE"
} 

And when I invoke a certain method on the system, the service should be in active state after x amount of time (unknown time):

someService().startService(); //after a while, the state of the service should be active

If i wanted to check the service state just once, i would do this:

public boolean checkCurrentState(String modeToCheck){
      return getServiceState() == modeToCheck; 
}

checkCurrentState("ACTIVE"); //return true or false depends on the state

Problem is, the state takes some time to change, so I need the following:

I need to check the current state (in a while loop for x amount of seconds defined by me), if after x seconds the service is still in "NOTACTIVE" mode, I will throw some kind of exception to terminate my program.

So I thought of the following solution: A method that has 2 variables: a variable that represents a generic function which can be invoked inside of the method, and a variable which is the time I allow for it to keep checking: (pseudo code)

public void runGenericForXSeconds(Func function,int seconds) throws SOMEEXCEPTION{
      int timeout = currentTime + seconds; //milliseconds
      while (currentTime < timeout){
           if (function.invoke()) return; //if true exits the method, for the rest of the program, we are all good
      }
      throw new SOMEEXCEPTION("something failed"); //the function failed
}

Something of that sorts, but I need it as generic as possible (the invoked method part should take other methods), Java 8 lambdas are part of the solution?


Solution

  • Using your example specifically:

    public void runGenericForXSeconds(BooleanSupplier supplier, int seconds) throws SOMEEXCEPTION {
        int timeout = currentTime + seconds; // milliseconds
        while (currentTime < timeout) {
            if (supplier.getAsBoolean())
                return; // if true exits the method, for the rest of the program, we are all good
        }
        throw new SOMEEXCEPTION("something failed"); // the function failed
    }
    

    Then your supplier just needs to return true or false. E.g.:

    runGenericForXSeconds(() -> !checkCurrentState("ACTIVE"), 100);
    

    Note that you have a busy loop. Unless you explicitly want this you might want to pause between invocations using Thread.sleep() or similar.