I am in the following situation (perhaps I have overengineered the whole thing or I am in a complete deadlock, but cannot think to another way of doing that):
- Take one or more
FutureTask
that realize an asynchronous computation (listening of the network for multicast packets conveing statistics of different kinds), we will name itMulticastStatisticsProvider
, - Take another computation that depends on this first task to perform an extra computation (combining statistics with formulas to expose some synthetic informations), this computation is also asynchronous so defined in another
FutureTask
that we will callFormulaComputing
, - Problem: We want that
FormulaComputing.get(timeout, timeUnit)
propagates the timeout to its innerCallable
when it callsMulticastStatisticsProvider.get(timeout, timeUnit)
and cannot find a way to achieve this.
Hereunder, the state of code I achieve so far:
This is the caller code.
// This is the code creating the formula computing code. public FormulaComputing getFormulaComputing() { // Retrieve from another service a list of FutureTasks already // scheduled for execution in their own ThreadPool. List<MulticastStatisticsProvider> requiredTasks = service.getRequiredTasks(); // Create the formulaComputing task and schedule it for execution FormulaComputing formulaComputing = new FormulaComputing(requiredTasks); threadPool.execute(formulaComputing); return formulaComputing; } // And then, from another caller getFormulaComputing().get(10, TimeUnit.SECONDS);
This is the
FormulaComputing
code:public class FormulaComputing extends FutureTask<Object> { private long timeout; private TimeUnit timeUnit; private Map<String, Future<Map<String, ? extends AbstractSymposiumMessage>>> promises; private Closure<Object> callback; public FormulaComputing(List<MulticastStatisticsProvider> dependentTasks, Closure<Object> callback) { super(new Callable<Object>() { @Override public Object call() throws Exception { List<Object> results = new ArrayList<Object>(); for (MulticastStatisticsProvider task : dependentTasks) { // Here is the problem, you cannot access field values in constructor: "Cannot refer to an instance method while explicitly invoking a constructor". results.add(task.get(getTimeout(), getTimeUnit())); } return callback.call(results.toArray()); } }); } @Override public Object get(long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { this.timeout = timeout; this.timeUnit = timeUnit; return super.get(timeout, timeUnit); } }
I have imagined passing by introspection to alter private inner sync
field of FutureTask
with my hand-made Callable
in my custom get
method, but introspection and reflection are generally avoidable hacks.