1
resposta

Capturar Exceções de m Callable sem travar a Thread Principal?

Uma dúvida que tinha antes de assistir a aula era exatamente como contornar o problema do método get da classe future bloquear a thread da classe que chamou o callable, dúvida essa que foi sanada com a aula.

Porém gostaria de saber se na minha classe Callable eu lançar uma exceção de negócio e na classe que eu invoquei esse callable eu quiser capturar esta exceção e lançar uma mensagem para o usuário da exceção que ocorreu através de um JOptionPane por exemplo, está operação também vai bloquear a thread principal igual ao método get() de Future? em caso afirmativo como contornar?

public class ComandoC2ChamaWs implements Callable<String> {
    @Override
    public String call() throws Exception {
           if(algumaCondicaoQueNaoFoiSatisfeita){
throw new Exception("o valor xxx tem que obedecer critério yyy");
    }
}
switch (comando) {    
    case "c2": {
        ComandoC2ChamaWs c2WS = new ComandoC2ChamaWs(saidaCliente);
// *como capturar as exceções neste trecho quem sem ter bloqueio da thread ?
        Future<String> futureWS = this.threadPool.submit(c2WS);
        break;
    }
}
1 resposta

Oi Ricardo! Tudo bem?

Excelente a sua pergunta. Quando trabalhamos com pool, temos uma concorrência entre as execuções que não se pode determinar quando a resposta será retornada já que a natureza de execução é assíncrona.

Apenas como curiosidade, para resolver esse problema, existe um pattern chamado observer, onde você registra junto ao Executor, um método que ele precisa chamar quando a operação termina. Junto do Executor, se tem uma referência para o resultado do processamento e uma possível exceção.

https://en.wikipedia.org/wiki/Observer_pattern

Para não complicar seu desenvolvimento existem APIs que facilitam a vida, como usar Guava do Google, que basicamente implementam esse Design Pattern

ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
  public Explosion call() {
    return pushBigRedButton();
  }
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
  // we want this handler to run immediately after we push the big red button!
  public void onSuccess(Explosion explosion) {
    walkAwayFrom(explosion);
  }
  public void onFailure(Throwable thrown) {
    battleArchNemesis(); // escaped the explosion!
  }
});

Para mais informações de uso do Guava, recomendo dar uma olhada no link.

https://github.com/google/guava/wiki/ListenableFutureExplained

Espero ter ajudado,

Abraço e sucesso!

Rodrigo