Search code examples
javaconcurrencyjava.util.concurrent

How to tell Java Futures apart?


It seems like I should be able to tell Futures apart from each other without having to maintain two HashMaps (or one bidirectional hash).

  1. Future is known when job is submitted to ExecutorService. Add Future to map with key 'jobID'.
  2. If job needs to be canceled, use 'jobID' in map to retrieve Future and cancel.
  3. If job completes successfully, Future can be identified by the returned Object (containing job ID). Remove Future from map via 'jobID'.
  4. If job is interrupted or throws an exception, no Object is returned, so the Future must be matched with the 'jobID' via calls to Future.hashCode or Future.equals (hence, two HashMaps or one bidirectional third-party hash).

Am I missing something here, or is that the expected approach? I'd like to override Future to include a 'getId' method or something, but that doesn't seem feasible based on how the executor creates them.

Edit: I'm also trying to use ExecutorCompletionService to wait for jobs to be completed.


Solution

  • Never use java.util.concurrent.Future. Use com.google.common.util.concurrent.ListenableFuture or similar instead. With ListenableFutures you can register callbacks when a ListenableFuture completes:

    ListenableFuture<Integer> future = MoreExecutors.listeningDecorator(executor).submit(
      new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
          ...
        }
    });
    
    // Add jobId to the map. You should use a thread-safe Map!
    map.put(jobId, future);
    
    Futures.addCallback(future, new FutureCallback<Integer>(){
      @Override
      public void onSuccess(Integer result) {
        map.remove(jobId);
        ...
      }
    
      @Override
      public void onFailure(Throwable t) {
        map.remove(jobId);
        ...
      }});