230 votes

Comment mettre en place un re-try-catch?

Try-catch est destiné à les aider dans la gestion des exceptions. Cela signifie en quelque sorte que cela va aider notre système pour être plus robuste: tenter de récupérer à partir d'un événement inattendu.

On soupçonne que quelque chose pourrait se produire lors de l'exécution et de l'instruction (envoi d'un message), donc il s'est enfermé dans le coup d'essayer. Si quelque chose de presque inattendu se produit, nous pouvons faire quelque chose: nous écrire à l'attraper. Je ne pense pas que nous avons appelé à juste enregistrer l'exception. Je chose que le bloc catch est censé nous donner la possibilité de récupérer de l'erreur.

Maintenant, disons que nous récupérer à partir de l'erreur, car nous avons pu corriger ce qui n'allait pas. Il pourrait être super gentil de faire un re-essayer:

try{ some_instruction(); }
catch (NearlyUnexpectedException e){
   fix_the_problem();
   retry;
}

Ce serait très vite tomber dans l'éternelle boucle, mais disons que le fix_the_problem retourne true, alors nous réessayer. Étant donné qu'il n'existe pas en Java, comment voulez-VOUS résoudre ce problème? Quel serait votre meilleur code de conception pour résoudre ce problème?

C'est comme une question philosophique, étant donné que je sais déjà ce que je demande n'est pas directement pris en charge par Java.

367voto

Rohit Jain Points 90368

Vous devez placer votre try-catch à l'intérieur d'un while boucle comme ceci: -

int count = 0;
int maxTries = 3;
while(true) {
    try {
        // Some Code
        // break out of loop, or return, on success
    } catch (SomeException e) {
        // handle exception
        if (++count == maxTries) throw e;
    }
}

J'ai pris l' count et maxTries pour éviter de courir dans une boucle infinie, dans le cas où l'exception garde sur le qui se produisent dans votre try block.

65voto

ach Points 2279

Obligatoire "enterprisy" solution:

public abstract class Operation {
    abstract public void doIt();
    public void handleException(Exception cause) {
        //default impl: do nothing, log the exception, etc.
    }
}

public class OperationHelper {
    public static void doWithRetry(int maxAttempts, Operation operation) {
        for (int count = 0; count < maxAttempts; count++) {
            try {
                operation.doIt();
                count = maxAttempts; //don't retry
            } catch (Exception e) {
                operation.handleException(e);
            }
        }
    }
}

Et l'appel de:

OperationHelper.doWithRetry(5, new Operation() {
    @Override public void doIt() {
        //do some stuff
    }
    @Override public void handleException(Exception cause) {
        //recover from the Exception
    }
});

37voto

meriton Points 30447

Comme d'habitude, la meilleure conception en fonction des circonstances particulières. Cependant, d'ordinaire, j'écris quelque chose comme:

for (int retries = 0;; retries++) {
    try {
        return doSomething();
    catch (SomeException e) {
        if (retries < 6) {
            continue;
        } else {
            throw e;
        }
    }
}

19voto

AlexR Points 60796

Bien qu' try/catch en while est bien connue et de bonne stratégie, je veux vous suggérer appel récursif:

void retry(int i, int limit) {
    try {

    } catch (SomeException e) {
        // handle exception
        if (i >= limit) {
            throw e;  // variant: wrap the exception, e.g. throw new RuntimeException(e);
        }
        retry(i++, limit);
    }
}

18voto

yegor256 Points 21737

Vous pouvez utiliser des AOP et des annotations Java à partir de jcabi-aspects (je suis développeur):

@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
  return url.openConnection().getContent();
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X