Search code examples
javascheduled-tasksjava-threads

ScheduledExecutorService end after a timeout


Good day! I have scheduler and I need to check how much time does it works. How can I do that? I need to return an error from someFunction() when scheduler works more than 5 minutes

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

public int someFunction() {
    ScheduledFuture<Integer> future = 
        scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS);
    if (scheduler.isShutdown()) {
        return future.get();
    }
}
private class ScheduledPrinter implements Callable<Integer> {
    public Integer call() throws Exception {
        // do something
        if (!serverResponse.getErrorData().equals("QueueIsNotReady")) {
            scheduler.shutdown();
            return getResponse();
        } 
        return null;
    }
}

Solution

  • You can use following options:

    1. scheduler.awaitTermination(5, TimeUnit.MINUTES)

      ScheduledFuture<Integer> future = 
              scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS);
      if (!scheduler.awaitTermination(5, TimeUnit.MINUTES)) {
          throw new Exception("task did not complete");
      } 
      
    2. future.get(5, TimeUnit.MINUTES). This method allows you to reuse scheduler for other tasks:

      ScheduledFuture<Integer> future =
              scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS);
      future.get(5, TimeUnit.MINUTES)); // this will throw TimeoutException after 5 minutes
      
    3. Schedule another task to run in 5 minutes that will check first task status. This method can be used for asynchronous handling of timeout. someFunction will return immediately in this case:

      ScheduledFuture<Integer> future =
              scheduler.schedule(new ScheduledPrinter(), 10, TimeUnit.SECONDS);
      scheduler.schedule(() -> {
          if (!future.isDone()) {
              future.cancel(true);  // cancel task if it runs more than 5 minutes
          }
      }, 5, TimeUnit.MINUTES);