Search code examples
javaconcurrencyfuturetask

Get result from FutureTask after canceling it


Consider a long running computation inside Callable instance.

And consider that the result of this computation can have some precision depending on computation time, i.e.: if task will be cancled than it should return what is computed so far before canceling (for example, we have a conveyor of irrational numbers calculating).

It is desirable to implement this paradigm using standard java concurency utils, e.g.

Callable<ValuableResult> task = new Callable<>() { ... };
Future<ValuableResult> future = Executors.newSingleThreadExecutor().submit(task);
try {
    return future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException te) {
    future.cancel(true);
    // HERE! Get what was computed so far
}

It seems, that without full reimplementing of Future and ThreadPoolExecutor interfaces this issue can not be solved. Are any convient existing tools for that in Java 1.7?


Solution

  • Well, it seems to me, that the most simple way in this case is to prepare some final ResultWrapper object, which will be passed inside this Callable instance:

    final ValuableResultWrapper wrapper = new ValuableResultWrapper();
    final CountDownLatch latch = new CountDownLatch(1);
    
    Callable<ValuableResultWrapper> task = new Callable<>() { 
       ... 
       wrapper.setValue(...); // here we set what we have computed so far
       latch.countDown();
       return wrapper;
       ...  
    };
    Future<ValuableResultWrapper> future = Executors.newSingleThreadExecutor().submit(task);
    try {
        return future.get(timeout, TimeUnit.SECONDS);
    } catch (TimeoutException te) {
        future.cancel(true);
        // HERE! Get what was computed so far
        latch.await();
        return wrapper;
    }
    

    UPD: In such implemetation (which becomes to complicated) we have to introduce some kind of latch (CountDownLatch in my example) to be sure, that task will be completed before we done return wrapper;