2012-07-17 20 views
8

Quiero esperar dos tareas para terminar y luego devolver el resultado de ellas, pero a veces me sale este error. ¿Por qué? ¿De dónde vino CancellationException?CancelaciónExcepción al utilizar ExecutorService

public class ShouldVoteTask extends AbstractWorkerTask<Void, Void, Boolean> { 
    private final int placeID; 
    private final int userID; 

    public ShouldVoteTask(final int placeID, final int userID) { 
     this.placeID = placeID; 
     this.userID = userID; 
    } 

    @Override 
    protected Boolean doInBackground(final Void... params) { 
     try { 
      // Prepare callables. 
      final IsMaxRatingCallable call1 = new IsMaxRatingCallable(placeID); 
      final DidVoteCallable call2 = new DidVoteCallable(placeID, userID);   
      final List<Callable<Boolean>> callables = new ArrayList<Callable<Boolean>>();   
      callables.add(call1); 
      callables.add(call2); 

      // Execute them. 
      final ExecutorService service = Executors.newFixedThreadPool(2);    
      final List<Future<Boolean>> futures = service.invokeAll(callables, 5, TimeUnit.SECONDS); 

      // Check the result. 
      boolean result = true; 
      for(final Future<Boolean> future : futures) { 
       if(future.get()) { 
        result = false; 
       } 
      } 

      return result; 
     } catch (final InterruptedException e) { 
      e.printStackTrace(); 
     } catch (final ExecutionException e) { 
      e.printStackTrace(); 
     } 
     return false; 
    } 
} 

private class IsMaxRatingCallable implements Callable<Boolean> { 
    private final int placeID; 

    public IsMaxRatingCallable(final int placeID) { 
     this.placeID = placeID; 
    } 

    @Override 
    public Boolean call() throws Exception { 
     return Places.isMaxRating(placeID);   
    } 
} 

private class DidVoteCallable implements Callable<Boolean> { 
    private final int placeID; 
    private final int userID; 

    public DidVoteCallable(final int placeID, final int userID) { 
     this.placeID = placeID; 
     this.userID = userID; 
    } 

    @Override 
    public Boolean call() throws Exception { 
     return Votes.didVote(placeID, userID);   
    } 
} 

error

E/AndroidRuntime(19014): FATAL EXCEPTION: AsyncTask #1 
E/AndroidRuntime(19014): java.lang.RuntimeException: An error occured while executing doInBackground() 
E/AndroidRuntime(19014): at android.os.AsyncTask$3.done(AsyncTask.java:200) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
E/AndroidRuntime(19014): at java.lang.Thread.run(Thread.java:1027) 
E/AndroidRuntime(19014): Caused by: java.util.concurrent.CancellationException 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.get(FutureTask.java:83) 
E/AndroidRuntime(19014): at com.vfa.android.planet.task.ShouldVoteTask.doInBackground(ShouldVoteTask.java:43) 
E/AndroidRuntime(19014): at com.vfa.android.planet.task.ShouldVoteTask.doInBackground(ShouldVoteTask.java:1) 
E/AndroidRuntime(19014): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
E/AndroidRuntime(19014): ... 4 more 
+0

qué línea es la línea 43? ¿Y qué hay en la línea 1? Es realmente extraño que tu rastro de pila muestre la línea 1. –

+0

43 >>> if (future.get()) {¿Qué pasa? – Emerald214

+0

Supongo que uno de tus callables lanzó una excepción. ¿Podrías publicar el código para esos? –

Respuesta

20

le pida a su servicio ejecutor para ejecutar sus callables con un tiempo de espera de 5 segundos. De acuerdo con the javadoc:

tareas que no han completado [a finales del tiempo de espera] se cancelan

Mi conjetura es que future.get() tiros un CancellationException debido a que el tiempo de espera se ha alcanzado y el ejecutor llama future.cancel() .

Usted podría:

  • aumentar el tiempo de espera
  • coger un InterruptedException en su exigible para manejar la cancelación con gracia
+0

Pero 'CancellationException' no extiende' InterruptedException' ¿verdad? –

+0

Por cierto, estoy tratando 'InterruptedException' alrededor de' invokeAll' y todavía tengo 'CancellationException' –

+0

@ LuísSoares No, no es así. – assylias

Cuestiones relacionadas