Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The way an <code>ExecutorService</code> works is that when you call <code>invokeAll</code> it waits for all tasks to complete:</p> <blockquote> <p>Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list. <strong>Note that a completed task could have terminated either normally or by throwing an exception</strong>. The results of this method are undefined if the given collection is modified while this operation is in progress.<sup><a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll%28java.util.Collection%29">1</a></sup>(emphasis added)</p> </blockquote> <p>What that means is that your tasks are all done but some may have thrown an exception. This exception is part of the <code>Future</code> - calling <code>get</code> causes the exception to be rethrown wrapped in an <code>ExecutionException</code>.</p> <p>From you stacktrack</p> <pre><code>java.util.concurrent.ExecutionException: java.lang.NullPointerException at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) at java.util.concurrent.FutureTask.get(Unknown Source) at ^^^ &lt;-- from get </code></pre> <p>You can see that this is indeed the case. One of your tasks has failed with an NPE. The <code>ExecutorService</code> caught the exception and is telling you about it by throwing an <code>ExecutionException</code> when you call <code>Future.get</code>.</p> <p>Now, if you want to take tasks <em>as they complete</em> you need an <code>ExecutorCompletionService</code>. This acts as a <code>BlockingQueue</code> that will allow you to poll for tasks as and when they finish.</p> <pre><code>public static void main(String[] args) throws Exception { final ExecutorService executorService = Executors.newFixedThreadPool(10); final ExecutorCompletionService&lt;String&gt; completionService = new ExecutorCompletionService&lt;&gt;(executorService); executorService.submit(new Runnable() { @Override public void run() { for (int i = 0; i &lt; 100; ++i) { try { final Future&lt;String&gt; myValue = completionService.take(); //do stuff with the Future final String result = myValue.get(); System.out.println(result); } catch (InterruptedException ex) { return; } catch (ExecutionException ex) { System.err.println("TASK FAILED"); } } } }); for (int i = 0; i &lt; 100; ++i) { completionService.submit(new Callable&lt;String&gt;() { @Override public String call() throws Exception { if (Math.random() &gt; 0.5) { throw new RuntimeException("FAILED"); } return "SUCCESS"; } }); } executorService.shutdown(); } </code></pre> <p>In this example I have one task that calls <code>take</code> on the <code>ExecutorCompletionService</code> which gets the <code>Future</code>s as they become available and then I submit tasks to the <code>ExecutorCompletionService</code>.</p> <p>This will allow you to get the failed task as soon as it fails rather than having to wait for all the tasks to either fail of succeed together.</p> <p>The only complication is that it is difficult to tell the polling thread that all the tasks are done as everything is now asynchronous. In this instance I have used the knowledge that 100 tasks will be submitted so that it only need to poll 100 times. A more general way would be to collect the <code>Future</code>s from the <code>submit</code> method as well and then loop over them to see if everything is completed.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload