异常

时间:2015-04-22 13:25:15

标签: java android abstract-class

如果抛出一些异常,我已经使这个抽象类自动重试网络调用。

  • 我注意不要在InterruptedException之后重试 UnknownHostException
  • 我重试了5次。每次失败后 我执行指数后退,从300ms开始 1500毫秒。
public abstract class AutoRetry {

  private Object dataToReturn = null;
  public Object getDataToReturn() {
    return this.dataToReturn;
  }

  public AutoRetry() {

    short retry = -1;
    while (retry++ < StaticData.NETWORK_RETRY) {

      try {
        Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
        this.dataToReturn = doWork();
        break;
      } catch (InterruptedException | UnknownHostException e) {
        e.printStackTrace();
        this.dataToReturn = null;
        return;
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  protected abstract Object doWork() throws IOException;
}

我按如下方式使用它:

final Object dataAfterWork = new AutoRetry() {     
  @Override
  protected Object doWork() throws IOException {
    return; //a network call which returns something
  }
}.getDataToReturn();

这个实现是否正确/正确?

修改

已移至https://codereview.stackexchange.com/questions/87686

2 个答案:

答案 0 :(得分:3)

看看Failsafe。它支持重试策略,同步和异步重试,事件监听器,与Java 8的CompletableFuture集成等。例如:

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(ConnectException.class)
  .withDelay(1, TimeUnit.SECONDS)
  .withMaxRetries(100);

// Synchronous get with retries
Connection connection = Failsafe.with(retryPolicy).get(() -> connect());

// Asynchronous get with retries
Failsafe.with(retryPolicy, executor)
  .get(() -> connect())
  .onSuccess(connection -> log.info("Connected to {}", connection))
  .onFailure(failure -> log.error("Connection attempts failed", failure));

答案 1 :(得分:2)

这看起来很不错,但我会从重试中拆分正在运行的任务。同样使用泛型,不要只是抛出Object

使用Java 8 lambda和方法的return

public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
    for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
        try {
            Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
            return Optional.of(t.get());
        } catch (InterruptedException | UnknownHostException e) {
            LOGGER.log(Level.SEVERE, "Call failed.", e);
            return Optional.empty();
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
        }
    }
    LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
    return Optional.empty();
}

另外,使用真实记录器,而不是printStackTrace ...

用法:

final String data = doWithRetry(() -> {
   //do stuff 
});

如果你的lambda需要抛出异常,你需要定义自己的@FunctionalInterface

@FunctionalInterface
interface StuffDoer<T> {
    T doStuff() throws Exception;
}

在方法签名中使用它,您需要处理通用Exception

Pre-Java 8用法:

final String data = doWithRetry(new StuffDoer<T>() {
    @Override
    public T get() throws Exception {
        return null;
    }
});