• Java Retry implement


    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:

  • 相关阅读:
    第四周作业及总结
    第三周作业及其总结
    第二周作业及总结
    我所敬佩的老师
    秋季学习总结
    自我介绍
    寒三总结
    2019春第7周作业
    2019春第六周作业
    2019春第五周作业
  • 原文地址:https://www.cnblogs.com/feika/p/4585922.html
Copyright © 2020-2023  润新知