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?
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;