74 Stimmen

Entwurfsmuster für die Wiederholung einer fehlgeschlagenen Logik?

Ich schreibe einige Reconnect-Logik, um regelmäßig zu versuchen, eine Verbindung zu einem entfernten Endpunkt herzustellen, der ausgefallen ist. Im Wesentlichen sieht der Code wie folgt aus:

public void establishConnection() {
    try {
        this.connection = newConnection();
    } catch (IOException e) {
        // connection failed, try again.
        try { Thread.sleep(1000); } catch (InterruptedException e) {};

        establishConnection();
    }
}

Ich habe dieses allgemeine Problem schon oft mit ähnlichem Code gelöst, aber ich bin mit dem Ergebnis weitgehend unzufrieden. Gibt es ein Entwurfsmuster für die Lösung dieses Problems?

7voto

db80 Punkte 3678

Sie können versuchen spring-retry Es hat eine übersichtliche Oberfläche und ist einfach zu bedienen.

Exemple :

 @Retryable(maxAttempts = 4, backoff = @Backoff(delay = 500))
 public void establishConnection() {
    this.connection = newConnection();
 } 

Im Falle einer Ausnahme wird die Methode bis zu 4 Mal wiederholt (aufgerufen) Verbindung aufbauen() mit einer Backoff-Politik von 500ms

3voto

klusht Punkte 31

Sie können auch eine Wrapper-Funktion erstellen, die nur eine Schleife über den beabsichtigten Vorgang ausführt und dann die Schleife einfach verlässt.

public static void main(String[] args) {
    retryMySpecialOperation(7);
}

private static void retryMySpecialOperation(int retries) {
    for (int i = 1; i <= retries; i++) {
        try {
            specialOperation();
            break;
        }
        catch (Exception e) {
            System.out.println(String.format("Failed operation. Retry %d", i));
        }
    }
}

private static void specialOperation() throws Exception {
    if ((int) (Math.random()*100) % 2 == 0) {
        throw new Exception("Operation failed");
    }
    System.out.println("Operation successful");
}

2voto

Ravipati Praveen Punkte 376

Wenn Sie Java 8 verwenden, kann dies helfen.

import java.util.function.Supplier;

public class Retrier {
public static <T> Object retry(Supplier<T> function, int retryCount) throws Exception {
     while (0<retryCount) {
        try {
            return function.get();
        } catch (Exception e) {
            retryCount--;
            if(retryCount == 0) {
                throw e;
            }
        }
    }
    return null;
}

public static void main(String[] args) {
    try {
        retry(()-> {
            System.out.println(5/0);
            return null;
        }, 5);
    } catch (Exception e) {
        System.out.println("Exception : " + e.getMessage());
    }
}
}

Danke,

Praveen R.

2voto

Valeriy K. Punkte 1956

Ich benutze Wiederholung4j Bibliothek. Beispiel für Testcode:

public static void main(String[] args) {
    Callable<Object> callable = () -> {
        doSomething();
        return null;
    };

    RetryConfig config = new RetryConfigBuilder()
            .retryOnAnyException()
            .withMaxNumberOfTries(3)
            .withDelayBetweenTries(5, ChronoUnit.SECONDS)
            .withExponentialBackoff()
            .build();

    new CallExecutorBuilder<>().config(config).build().execute(callable);
}

public static void doSomething() {
    System.out.println("Trying to connect");
    // some logic
    throw new RuntimeException("Disconnected"); // init error
    // some logic
}

1voto

Vishal Kharde Punkte 1339

Hier ist ein anderer Ansatz, um die Wiederholung durchzuführen. Keine Bibliotheken, keine Anmerkungen, keine zusätzlichen Implementierungen. Import java.util.concurrent.TimeUnit;

public static void myTestFunc() {
        boolean retry = true;
        int maxRetries = 5;   //max no. of retries to be made
        int retries = 1;
        int delayBetweenRetries = 5;  // duration  between each retry (in seconds)
        int wait = 1;
    do {
        try {
            this.connection = newConnection();
            break;
        }
        catch (Exception e) {
            wait = retries * delayBetweenRetries;
            pause(wait);
            retries += 1;
            if (retries > maxRetries) {
                retry = false;
                log.error("Task failed on all of " + maxRetries + " retries");
            }
        }
    } while (retry);

}

public static void pause(int seconds) {
    long secondsVal = TimeUnit.MILLISECONDS.toMillis(seconds);

    try {
        Thread.sleep(secondsVal);
    }
    catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X