草庐IT

java - 异常后自动重试的功能

coder 2023-12-21 原文

我已经使这个抽象类在抛出某些异常时自动重试网络调用。

  • 我注意不要在 InterruptedException 之后重试 & 未知主机异常
  • 我重试了 5 次。每次失败后 我执行指数回退,从 300 毫秒开始上升到 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

最佳答案

这看起来不错,但我会将正在运行的任务与重试分开。也使用泛型,不要只是抛出 Object about。

使用 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

Java 8 之前的用法:

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

关于java - 异常后自动重试的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29799001/

有关java - 异常后自动重试的功能的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  5. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  6. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  7. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  8. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐