There are many cases in which you may wish to retry an operation a certain number of times. Examples are database failures, network communication failures or file IO problems.

Approach 1
This is the traditional approach and involves a counter and a loop.

final int numberOfRetries = 5 ;
final long timeToWait = 1000 ;
 
for (int i=0; i<numberOfRetries; i++) {
 //perform the operation
 try {
  Naming.lookup("rmi://localhost:2106/MyApp");
  break;
 }
 catch (Exception e) {
  logger.error("Retrying...",e);
  try {
   Thread.sleep(timeToWait);
  }
  catch (InterruptedException i) {
  }
 }
}

Approach 2
In this approach, we hide the retry counter in a separate class called RetryStrategy and call it like this:

public class RetryStrategy
{
 public static final int DEFAULT_NUMBER_OF_RETRIES = 5;
 public static final long DEFAULT_WAIT_TIME = 1000;
 
 private int numberOfRetries; //total number of tries
 private int numberOfTriesLeft; //number left
 private long timeToWait; //wait interval
 
 public RetryStrategy()
 {
  this(DEFAULT_NUMBER_OF_RETRIES, DEFAULT_WAIT_TIME);
 }
 
 public RetryStrategy(int numberOfRetries, long timeToWait)
 {
  this.numberOfRetries = numberOfRetries;
  numberOfTriesLeft = numberOfRetries;
  this.timeToWait = timeToWait;
 }
 
 /**
  * @return true if there are tries left
  */
 public boolean shouldRetry()
 {
  return numberOfTriesLeft > 0;
 }
 
 /**
  * This method should be called if a try fails.
  *
  * @throws RetryException if there are no more tries left
  */
 public void errorOccured() throws RetryException
 {
  numberOfTriesLeft --;
  if (!shouldRetry())
  {
   throw new RetryException(numberOfRetries +
     " attempts to retry failed at " + getTimeToWait() +
     "ms interval");
  }
  waitUntilNextTry();
 }
 
 /**
  * @return time period between retries
  */
 public long getTimeToWait()
 {
  return timeToWait ;
 }
 
 /**
  * Sleeps for the duration of the defined interval
  */
 private void waitUntilNextTry()
 {
  try
  {
   Thread.sleep(getTimeToWait());
  }
  catch (InterruptedException ignored) {}
 }
 
 public static void main(String[] args) {
  RetryStrategy retry = new RetryStrategy();
  while (retry.shouldRetry()) {
   try {
    Naming.lookup("rmi://localhost:2106/MyApp");
    break;
   }
   catch (Exception e) {
    try {
     retry.errorOccured();
    }
    catch (RetryException e1) {
     e.printStackTrace();
    }
   }
  }
 }
}

Approach 3
Approach 2, although cleaner, hasn't really reduced the number of lines of code we have to write. In the next approach, we hide the retry loop and all logic in a separate class called RetriableTask. We make the operation that we are going to retry Callable and wrap it in a RetriableTask which then handles all the retrying for us, behind-the-scenes:

public class RetriableTask<T> implements Callable<T> {
 
 private Callable<T> task;
 public static final int DEFAULT_NUMBER_OF_RETRIES = 5;
 public static final long DEFAULT_WAIT_TIME = 1000;
 
 private int numberOfRetries; // total number of tries
 private int numberOfTriesLeft; // number left
 private long timeToWait; // wait interval
 
 public RetriableTask(Callable<T> task) {
  this(DEFAULT_NUMBER_OF_RETRIES, DEFAULT_WAIT_TIME, task);
 }
 
 public RetriableTask(int numberOfRetries, long timeToWait,
                      Callable<T> task) {
  this.numberOfRetries = numberOfRetries;
  numberOfTriesLeft = numberOfRetries;
  this.timeToWait = timeToWait;
  this.task = task;
 }
 
 public T call() throws Exception {
  while (true) {
   try {
    return task.call();
   }
   catch (InterruptedException e) {
    throw e;
   }
   catch (CancellationException e) {
    throw e;
   }
   catch (Exception e) {
    numberOfTriesLeft--;
    if (numberOfTriesLeft == 0) {
     throw new RetryException(numberOfRetries +
     " attempts to retry failed at " + timeToWait +
     "ms interval", e);
    }
    Thread.sleep(timeToWait);
   }
  }
 }
 
 public static void main(String[] args) {
  Callable<Remote> task = new Callable<Remote>() {
   public Remote call() throws Exception {
    String url="rmi://localhost:2106/MyApp";
    return (Remote) Naming.lookup(url);
   }
  };
 
  RetriableTask<Remote> r = new RetriableTask<Remote>(task);
  try {
   r.call();
  }
  catch (Exception e) {
   e.printStackTrace();
  }
 }
}

Also see:

References:

Java Retry implement的更多相关文章

  1. java retry:详解

    发现 今天在探秘线程池原理知识点,在阅读JDK源码时遇到程序代码中出现如下代码,因为之前没有遇到过,于是特地记录下来并谷歌了一番,后面我自己做了一些简要的验证和分析. 验证 网上溜达一番发现,这ret ...

  2. Effective Java 74 Implement Serializable judiciously

    Disadvantage of Serializable A major cost of implementing Serializable is that it decreases the flex ...

  3. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  4. Java Algorithm Problems

    Java Algorithm Problems 程序员的一天 从开始这个Github已经有将近两年时间, 很高兴这个repo可以帮到有需要的人. 我一直认为, 知识本身是无价的, 因此每逢闲暇, 我就 ...

  5. 为什么Java中的String是设计成不可变的?(Why String is immutable in java)

    There are many reasons due to the string class has been made immutable in Java. These reasons in vie ...

  6. 更好的 java 重试框架 sisyphus 入门简介

    What is Sisyphus sisyphus 综合了 spring-retry 和 gauva-retrying 的优势,使用起来也非常灵活. 为什么选择这个名字 我觉得重试做的事情和西西弗斯很 ...

  7. Jmeter3.0新特性

    2016-5-19昨日,Jmeter又更新了新版本. 那么新版本有哪些新特性呢? Changes   This page details the changes made in the current ...

  8. jackson官方快速入门文档

    官方地址: http://jackson.codehaus.org/ http://wiki.fasterxml.com/JacksonInFiveMinutes http://wiki.faster ...

  9. Maven聚合与继承的实例讲解(二)

    继续上一节讲Maven的内容,我们这个节继续讲Maven继承和聚合的其他内容.    现在我们新建一个实例来测试Maven有关于聚合的部分     测试开始 一.建立以pom为packaging的项目 ...

随机推荐

  1. BZOJ4311 向量(线段树分治+三分)

    由点积的几何意义(即投影)可以发现答案一定在凸壳上,并且投影的变化是一个单峰函数,可以三分.现在需要处理的只有删除操作,线段树分治即可. #include<iostream> #inclu ...

  2. ARC075 E.Meaningful Mean(树状数组)

    题目大意:给定n和k,问an中有多少子区间的平均值大于等于k 很巧妙的一个式子,就是如果一个区间[l, r]满足条件 那么则有 sum[r] - sum[l-1] >= (r-l+1)*k 整理 ...

  3. 【题解】SCOI2009围豆豆

    很久之前就很想做的一道题,一直思考到今天才下定决心看题解.这道题中,很关键的一点就在于:如何判断一个点是否在一个多边形内?其实如果计算几何基本功扎实的话,应该是可以很快给出答案的(可惜我完全不行):由 ...

  4. ContestHunter#17-C 舞动的夜晚

    Description: L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一 ...

  5. BZOJ4008. [HNOI2015]亚瑟王 期望概率dp

    看到这道题想什么? 一个好转移的状态由于T最多444所以把每个点控制在O(400000)以内,所以对于n和r最多乘一次因此猜f[n][r],f[r][n],首先一轮一轮的搞不好转移,那么先想一想f[n ...

  6. BigDecimal与Long、int之间的互换

    在实际开发过程中BigDecimal是一个经常用到的数据类型,它和int Long之间可以相互转换. 转换关系如下代码展示: int 转换成 BigDecimal 数据类型 //int 转换成 big ...

  7. hive的体系架构及安装

    1,什么是Hive? Hive是能够用类SQL的方式操作HDFS里面数据一个数据仓库的框架,这个类SQL我们称之为HQL(Hive Query Language) 2,什么是数据仓库? 存放数据的地方 ...

  8. 【UOJ131/NOI2015D2T2-品酒大会】sam求后缀树

    题目链接:http://uoj.ac/problem/131 题意:给出一个字符串,第i个字符对应的值为a[i], 对于i∈[0,n),求最长公共前缀大于等于i的字串对个数,并求这些字符串对开头对应值 ...

  9. bzoj1575 [Usaco2009 Jan]气象牛Baric

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1575 [题解] 动态规划,令f[i,j]表示前i个选了j个,且第i个必选的最小值. 转移就枚 ...

  10. USACO月赛2005 january volume

    2013-09-18 08:12 由题可知,ans=∑i  ∑j(x[i]-x[j]) 最后整理完之后应该是不同系数的X[i]相加,所以这道题就成了求不同x[i]的系数 对于X[i],它需要减前面(i ...