आप पुन: प्रयास-कैच कैसे लागू करते हैं?


203

ट्राइ-कैच अपवाद से निपटने में मदद करने के लिए है। इसका मतलब किसी भी तरह से यह हमारे सिस्टम को अधिक मजबूत बनाने में मदद करेगा: एक अप्रत्याशित घटना से उबरने का प्रयास करें।

हमें संदेह है कि निष्पादन और निर्देश (संदेश भेजते समय) कुछ हो सकता है, इसलिए यह कोशिश में संलग्न हो जाता है। यदि ऐसा कुछ अप्रत्याशित होता है, तो हम कुछ कर सकते हैं: हम कैच लिखते हैं। मुझे नहीं लगता कि हमने केवल अपवाद को लॉग करने के लिए बुलाया। मुझे लगता है कि कैच ब्लॉक हमें त्रुटि से उबरने का अवसर देने के लिए है।

अब, मान लें कि हम त्रुटि से उबर गए क्योंकि हम जो गलत था उसे ठीक कर सकते हैं। यह फिर से कोशिश करने के लिए सुपर अच्छा हो सकता है:

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

यह जल्दी से अनन्त लूप में आ जाएगा, लेकिन हम कहते हैं कि fix_the_problem सही है, तो हम फिर से प्रयास करते हैं। यह देखते हुए कि जावा में ऐसा कुछ नहीं है, आप इस समस्या को कैसे हल करेंगे? इसे हल करने के लिए आपका सबसे अच्छा डिज़ाइन कोड क्या होगा?

यह एक दार्शनिक प्रश्न की तरह है, यह देखते हुए कि मैं पहले से ही जानता हूं कि मैं जो मांग रहा हूं वह सीधे जावा द्वारा समर्थित नहीं है।


5
वह किस तरह का अपवाद है?
भेश गुरुंग

23
मुझे हालांकि आपके अपवाद का नाम पसंद है। ;)
रोहित जैन

विलेख में, ऐसे कई अपवाद नहीं हैं जिनसे आप ठीक हो सकते हैं। मैं मानता हूं कि मेरी प्रारंभिक प्रेरणा एक वास्तविक अपवाद नहीं थी, लेकिन अगर ऐसा न हो तो बचने का तरीका लगभग कभी नहीं होगा: मैं remove()एक से कोशिश करता हूं java.util.Queue, कौन सी थ्रू और InvalidElementExceptionकब कतार खाली है। यह पूछने के बजाय कि क्या यह खाली है, मैं एक कोशिश-कैच में क्रियाओं को घेर लेता हूं (जो संक्षिप्त के तहत पिछले के साथ भी अनिवार्य हो जाता है)। ऐसे मामले में, catchब्लॉक में मैं और तत्वों के साथ कतार को फिर से भरने के लिए कहूंगा और फिर, फिर से प्रयास करूँगा। देखा।
एंड्रेस फरियास

1
मैं देख सकता हूं कि ऐसा करने का सामान्य तरीका डीबी पहुंच के लिए होगा, यदि कनेक्शन फिर से कनेक्ट नहीं हुआ है, अगर यह विफल रहता है तो प्रमुख अपवाद को फेंक दें अन्यथा कॉल फिर से वापस लें। जैसा कि कहा गया है कि हम इसे लूप में नीचे की ओर एक चेक के साथ कर सकते हैं यदि (त्रुटि <> 0) तो वापस जाएं अन्यथा विराम;
थेरेसा फोर्स्टर

जवाबों:


304

आप अपने शामिल करनी try-catchएक के अंदर whileइस तरह पाश: -

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;
    }
}

मैंने लिया है countऔर maxTriesएक अनन्त लूप में चलने से बचने के लिए, यदि आपके में अपवाद होता रहता है try block


3
मैंने कुछ इस तरह से सोचा था, अधिकतम के बिना। जवाब के लिए धन्यवाद!
एंड्रेस फरियास

6
@AndresFarias .. हाँ, इस उत्तर में सबसे महत्वपूर्ण बिंदु एक को शामिल करना है maxTriesinfinite loopयदि यह उपयोगकर्ता गलत इनपुट देता है, और इसलिए बाहर नहीं निकलेगा, तो यह चल जाएगा। हालांकि आपका स्वागत है। :)
रोहित जैन

इसके लिए धन्यवाद - इसने मुझे कुछ बहुत ही स्पष्ट रूप से कोड लिखने से बचाया!
डेविड हॉलिडे

2
क्या यहां पर थ्रेड के अंदर थ्रेड.स्लीप () फ़ंक्शन जोड़ना संभव है। क्योंकि कुछ मामलों में जैसे सेलेनियम पुस्तकालय में पृष्ठ की प्रतिक्रिया का इंतजार करना महत्वपूर्ण हो गया था। धन्यवाद।
सुत अतान पीएचडी

2
बहुत अच्छा काम करता है! शुरुआती लोगों के लिए: यदि आपको सकारात्मक अनंत लूप मिलता है, तो जांचें कि क्या आपने "ब्रेक" जोड़ा है? "कोशिश" ब्लॉक में अंत में।
Krzysztof Walczewski

59

अप्रचलित "एन्ट्रापी" समाधान:

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);
            }
        }
    }
}

और कॉल करने के लिए:

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

6
यदि अंतिम पुन: प्रयास विफल रहता है, तो आपको अपवाद को फिर से फेंकना चाहिए, जैसा कि अन्य उत्तरों में दिया गया है।
cvacca

35

हमेशा की तरह, सबसे अच्छा डिजाइन विशेष परिस्थितियों पर निर्भर करता है। आमतौर पर, मैं कुछ लिखता हूं:

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

रुको, लूप डिक्लेरेशन के लिए स्थिति अंदर क्यों नहीं है जैसे: के लिए (int retries = 0; रिट्रीव्स <? Ret; ++ ++) ??
डिडिएर ए।

8
क्योंकि मैं केवल अंतिम प्रयास में फेंकना चाहता हूं, और इसलिए कैच ब्लॉक को उस स्थिति की आवश्यकता होती है, जिससे स्थिति निरर्थक हो जाती है।
मैरिटन

1
मुझे नहीं लगता है कि continueवहाँ की जरूरत है .. और आप बस अगर हालत फ्लिप कर सकते हैं।
कोरा तुगे

19

यद्यपि try/catchमें whileअच्छी तरह से जाना जाता है और अच्छी रणनीति है कि मैं आपको पुनरावर्ती कॉल का सुझाव देना चाहता हूं:

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);
    }
}

41
इस उपयोग के मामले के लिए एक लूप की तुलना में पुनरावृत्ति कैसे बेहतर है?
Dan

7
स्टैक ट्रेस इस पर थोड़ा अजीब लग सकता है, क्योंकि इसमें limitविधि की गणना नहीं की जाएगी? लूप संस्करण के विपरीत, जो 'मूल' स्तर पर फेंक देगा ...
घड़ी की कल-पज़ल

7
यकीन है कि कागज पर सुरुचिपूर्ण दिखता है, लेकिन मुझे यकीन नहीं है कि पुनरावृत्ति किसी भी तरह सही दृष्टिकोण है।
थॉमस

3
मुझे समझ में नहीं आ रहा है कि यहाँ भी पुनरावृत्ति क्यों होती है। वैसे भी, मुझे लगता है कि इसे सरल बनाया जा सकता है:void retry(int times) { (...) if (times==0) throw w; retry(times--);
सिनुहेपॉप

8
केवल पुनरावृत्ति के विकल्प के रूप में पुनरावृत्ति का उपयोग करना खराब अभ्यास है। जब आप किसी डेटा को पुश और पॉप करना चाहते हैं तो रिकर्सन उपयोग के लिए है।
लोर्ने

19

आपका सटीक परिदृश्य Failsafe के माध्यम से संभाला :

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(NearlyUnexpectedException.class);

Failsafe.with(retryPolicy)
  .onRetry((r, f) -> fix_the_problem())
  .run(() -> some_instruction());

बहुत साधारण।


5
बहुत अच्छी लाइब्रेरी।
Maksim

सोच रहे लोगों के लिए, आपको अपने ग्रेडेल निर्भरताओं में इसकी आवश्यकता होगी - संकलन 'net.jodah: failafe: 1.1.0'
श्रेयस

18

आप jcabi- पहलुओं (मैं एक डेवलपर हूं) से AOP और Java एनोटेशन का उपयोग कर सकते हैं :

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

आप उपयोग @Loggableऔर @LogExceptionएनोटेशन भी कर सकते हैं ।


वाह ! फैंसी लगता है! :)
अलिन्द बिलोर

शीर्ष उत्तर होना चाहिए।
मोहम्मद ताहिर अल्रेफ़ी

2
क्या प्रयास विफल होने पर त्रुटि को "ठीक" करने का एक तरीका है (कुछ प्रयास करें जो अगले प्रयास को ठीक कर सकते हैं)? : प्रश्न देखें fix_the_problem();कैच ब्लॉक में
warch

खुले मुद्दों की मात्रा को देखते हुए और स्वीकार किए गए बगों को तय किए हुए समय बीतने के बावजूद, मैं इस पुस्तकालय पर भरोसा नहीं करूंगा।
माइकल लीह्स

6

इनमें से अधिकांश उत्तर मूल रूप से समान हैं। मेरा भी है, लेकिन यह वह रूप है जो मुझे पसंद है

boolean completed = false;
Throwable lastException = null;
for (int tryCount=0; tryCount < config.MAX_SOME_OPERATION_RETRIES; tryCount++)
{
    try {
        completed = some_operation();
        break;
    }
    catch (UnlikelyException e) {
        lastException = e;
        fix_the_problem();
    }
}
if (!completed) {
    reportError(lastException);
}

एक कमी यह है कि आप fix_the_problemअंतिम प्रयास के बाद भी कॉल करते हैं। यही कारण है कि हो सकता है एक महंगा ऑपरेशन हो सकता है और कुछ समय बर्बाद कर सकता है।
जोकिम सॉर

2
@JoachimSauer सच। आप कर सकते हैं if (tryCount < max) fix()- लेकिन यह एक सामान्य दृष्टिकोण का प्रारूप है; विवरण एक विशिष्ट मामले पर निर्भर करेगा। एक अमरूद आधारित रिट्रीर भी है जिसे मैं देख रहा हूं।
स्टीफन पी।

4

स्प्रिंग AOP और एनोटेशन आधारित समाधान:

उपयोग ( @RetryOperationनौकरी के लिए हमारा कस्टम एनोटेशन है):

@RetryOperation(retryCount = 1, waitSeconds = 10)
boolean someMethod() throws Exception {
}

इसे पूरा करने के लिए हमें दो चीजों की आवश्यकता होगी: 1. एक एनोटेशन इंटरफ़ेस, और 2. एक स्प्रिंग पहलू। इन्हें लागू करने का एक तरीका यह है:

एनोटेशन इंटरफ़ेस:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryOperation {
    int retryCount();
    int waitSeconds();
}

वसंत पहलू:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Aspect @Component 
public class RetryAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(RetryAspect.class);

    @Around(value = "@annotation(RetryOperation)")
    public Object retryOperation(ProceedingJoinPoint joinPoint) throws Throwable {

        Object response = null;
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        RetryOperation annotation = method.getAnnotation(RetryOperation.class);
        int retryCount = annotation.retryCount();
        int waitSeconds = annotation.waitSeconds();
        boolean successful = false;

        do {
            try {
                response = joinPoint.proceed();
                successful = true;
            } catch (Exception ex) {
                LOGGER.info("Operation failed, retries remaining: {}", retryCount);
                retryCount--;
                if (retryCount < 0) {
                    throw ex;
                }
                if (waitSeconds > 0) {
                    LOGGER.info("Waiting for {} second(s) before next retry", waitSeconds);
                    Thread.sleep(waitSeconds * 1000l);
                }
            }
        } while (!successful);

        return response;
    }
}

3

whileस्थानीय statusध्वज के साथ एक लूप का उपयोग करें । ध्वज को प्रारंभिक के रूप में falseसेट करें और इसे trueतब सेट करें जब ऑपरेशन सफल हो जैसे नीचे:

  boolean success  = false;
  while(!success){
     try{ 
         some_instruction(); 
         success = true;
     } catch (NearlyUnexpectedException e){
       fix_the_problem();
     }
  }

यह अपने सफल होने तक पुन: प्रयास करता रहेगा।

यदि आप केवल कुछ निश्चित समय को पुनः प्राप्त करना चाहते हैं, तो एक काउंटर का भी उपयोग करें:

  boolean success  = false;
  int count = 0, MAX_TRIES = 10;
  while(!success && count++ < MAX_TRIES){
     try{ 
         some_instruction(); 
         success = true;
     } catch (NearlyUnexpectedException e){
       fix_the_problem();
     }
  }
  if(!success){
    //It wasn't successful after 10 retries
  }

यह अधिकतम 10 बार प्रयास करेगा यदि तब तक सफल नहीं होता है जब तक कि हाथ से पहले सफल नहीं होगा।


!successअपने समय के लिए जाँच करने के बजाय , आप सफलता के सत्य होने पर, बस समय से बाहर तोड़ सकते हैं।
रोहित जैन

1
@ रोहितजैन: यह मुझे अधिक साफ दिखता है।
योगेंद्र सिंह

@ योगेंद्रसिंह .. अजीब बात है। जैसा कि आप अपने successकहीं भी अपने में संशोधन नहीं कर रहे हैं catch। अतः इसके हर दौर पर इसकी जाँच करना बेमानी लगता है catch
रोहित जैन

@ रोहितजैन: कैच सिर्फ डेटा को सही कर रहा है। यह वापस चला जाएगा और फिर से बयान चलाएगा। सफल होने पर, यह संशोधित करेगा success। कोशिश करके देखो।
योगेंद्र सिंह

3

यह एक पुराना प्रश्न है लेकिन एक समाधान अभी भी प्रासंगिक है। किसी भी तीसरे पक्ष के पुस्तकालय का उपयोग किए बिना जावा 8 में मेरा सामान्य समाधान है:

public interface RetryConsumer<T> {
    T evaluate() throws Throwable;
}
public interface RetryPredicate<T> {
    boolean shouldRetry(T t);
}
public class RetryOperation<T> {
    private RetryConsumer<T> retryConsumer;
    private int noOfRetry;
    private int delayInterval;
    private TimeUnit timeUnit;
    private RetryPredicate<T> retryPredicate;
    private List<Class<? extends Throwable>> exceptionList;

    public static class OperationBuilder<T> {
        private RetryConsumer<T> iRetryConsumer;
        private int iNoOfRetry;
        private int iDelayInterval;
        private TimeUnit iTimeUnit;
        private RetryPredicate<T> iRetryPredicate;
        private Class<? extends Throwable>[] exceptionClasses;

        private OperationBuilder() {
        }

        public OperationBuilder<T> retryConsumer(final RetryConsumer<T> retryConsumer) {
            this.iRetryConsumer = retryConsumer;
            return this;
        }

        public OperationBuilder<T> noOfRetry(final int noOfRetry) {
            this.iNoOfRetry = noOfRetry;
            return this;
        }

        public OperationBuilder<T> delayInterval(final int delayInterval, final TimeUnit timeUnit) {
            this.iDelayInterval = delayInterval;
            this.iTimeUnit = timeUnit;
            return this;
        }

        public OperationBuilder<T> retryPredicate(final RetryPredicate<T> retryPredicate) {
            this.iRetryPredicate = retryPredicate;
            return this;
        }

        @SafeVarargs
        public final OperationBuilder<T> retryOn(final Class<? extends Throwable>... exceptionClasses) {
            this.exceptionClasses = exceptionClasses;
            return this;
        }

        public RetryOperation<T> build() {
            if (Objects.isNull(iRetryConsumer)) {
                throw new RuntimeException("'#retryConsumer:RetryConsumer<T>' not set");
            }

            List<Class<? extends Throwable>> exceptionList = new ArrayList<>();
            if (Objects.nonNull(exceptionClasses) && exceptionClasses.length > 0) {
                exceptionList = Arrays.asList(exceptionClasses);
            }
            iNoOfRetry = iNoOfRetry == 0 ? 1 : 0;
            iTimeUnit = Objects.isNull(iTimeUnit) ? TimeUnit.MILLISECONDS : iTimeUnit;
            return new RetryOperation<>(iRetryConsumer, iNoOfRetry, iDelayInterval, iTimeUnit, iRetryPredicate, exceptionList);
        }
    }

    public static <T> OperationBuilder<T> newBuilder() {
        return new OperationBuilder<>();
    }

    private RetryOperation(RetryConsumer<T> retryConsumer, int noOfRetry, int delayInterval, TimeUnit timeUnit,
                           RetryPredicate<T> retryPredicate, List<Class<? extends Throwable>> exceptionList) {
        this.retryConsumer = retryConsumer;
        this.noOfRetry = noOfRetry;
        this.delayInterval = delayInterval;
        this.timeUnit = timeUnit;
        this.retryPredicate = retryPredicate;
        this.exceptionList = exceptionList;
    }

    public T retry() throws Throwable {
        T result = null;
        int retries = 0;
        while (retries < noOfRetry) {
            try {
                result = retryConsumer.evaluate();
                if (Objects.nonNull(retryPredicate)) {
                    boolean shouldItRetry = retryPredicate.shouldRetry(result);
                    if (shouldItRetry) {
                        retries = increaseRetryCountAndSleep(retries);
                    } else {
                        return result;
                    }
                } else {
                    // no retry condition defined, no exception thrown. This is the desired result.
                    return result;
                }
            } catch (Throwable e) {
                retries = handleException(retries, e);
            }
        }
        return result;
    }

    private int handleException(int retries, Throwable e) throws Throwable {
        if (exceptionList.contains(e.getClass()) || (exceptionList.isEmpty())) {
            // exception is excepted, continue retry.
            retries = increaseRetryCountAndSleep(retries);
            if (retries == noOfRetry) {
                // evaluation is throwing exception, no more retry left. Throw it.
                throw e;
            }
        } else {
            // unexpected exception, no retry required. Throw it.
            throw e;
        }
        return retries;
    }

    private int increaseRetryCountAndSleep(int retries) {
        retries++;
        if (retries < noOfRetry && delayInterval > 0) {
            try {
                timeUnit.sleep(delayInterval);
            } catch (InterruptedException ignore) {
                Thread.currentThread().interrupt();
            }
        }
        return retries;
    }
}

चलो एक परीक्षण के मामले की तरह है:

@Test
public void withPredicateAndException() {
    AtomicInteger integer = new AtomicInteger();
    try {
        Integer result = RetryOperation.<Integer>newBuilder()
                .retryConsumer(() -> {
                    int i = integer.incrementAndGet();
                    if (i % 2 == 1) {
                        throw new NumberFormatException("Very odd exception");
                    } else {
                        return i;
                    }
                })
                .noOfRetry(10)
                .delayInterval(10, TimeUnit.MILLISECONDS)
                .retryPredicate(value -> value <= 6)
                .retryOn(NumberFormatException.class, EOFException.class)
                .build()
                .retry();
        Assert.assertEquals(8, result.intValue());
    } catch (Throwable throwable) {
        Assert.fail();
    }
}

अच्छा विचार है, एक बिल्डर मेंढक है कि!
हैंकेनटैंक

2

समस्या को हल करने का एक सरल तरीका यह होगा कि कोशिश / पकड़ को थोड़ी देर के लिए लपेटें और एक गिनती बनाए रखें। इस तरह से आप अपनी विफलताओं के लॉग को बनाए रखते हुए कुछ अन्य चर के खिलाफ गिनती की जांच करके एक अनंत लूप को रोक सकते हैं। यह सबसे उत्तम समाधान नहीं है, लेकिन यह काम करेगा।


1

फिर से कोशिश ब्लॉक डिजाइन करने के लिए एक का उपयोग करें।

boolean successful = false;
int maxTries = 3;
do{
  try {
    something();
    success = true;
  } catch(Me ifUCan) {
    maxTries--;
  }
} while (!successful || maxTries > 0)

2
कोड को मूल अपवाद को फेंक देना चाहिए यदि असफल हो
lilalinux

1

मामले में यह उपयोगी है, एक जोड़े पर विचार करने के लिए और अधिक विकल्प, सभी को एक साथ फेंक दिया जाता है (वापसी के बजाय स्टॉपफाइल, नींद, बड़े लूप जारी रखें) सभी संभवतः सहायक।

 bigLoop:
 while(!stopFileExists()) {
    try {
      // do work
      break;
    }
    catch (ExpectedExceptionType e) {

       // could sleep in here, too.

       // another option would be to "restart" some bigger loop, like
       continue bigLoop;
    }
    // ... more work
}

मतदाता कृपया टिप्पणी छोड़ दें कि क्यों, धन्यवाद!
रोजरपैक

1
यह नीचता का अज्ञान है और एक कारण का हवाला नहीं देता है।
xploreraj

सोते समय स्पष्ट नहीं है क्योंकि लूप प्रतीक्षा नहीं करेगा
जोओ पेम्टेल फरेरा

1

आप https://github.com/bnsd55/RetryCatch का उपयोग कर सकते हैं

उदाहरण:

RetryCatch retryCatchSyncRunnable = new RetryCatch();
        retryCatchSyncRunnable
                // For infinite retry times, just remove this row
                .retryCount(3)
                // For retrying on all exceptions, just remove this row
                .retryOn(ArithmeticException.class, IndexOutOfBoundsException.class)
                .onSuccess(() -> System.out.println("Success, There is no result because this is a runnable."))
                .onRetry((retryCount, e) -> System.out.println("Retry count: " + retryCount + ", Exception message: " + e.getMessage()))
                .onFailure(e -> System.out.println("Failure: Exception message: " + e.getMessage()))
                .run(new ExampleRunnable());

इसके बजाय new ExampleRunnable()आप अपना स्वयं का अनाम फ़ंक्शन पास कर सकते हैं।


1

यदि सभी अपवाद केवल एक रिट्री को वारंट नहीं करते हैं, तो कुछ। और अगर कम से कम एक कोशिश करनी पड़े, तो यहां एक वैकल्पिक उपयोगिता विधि है:

void runWithRetry(Runnable runnable, Class<Exception> exClass, int maxRetries) {
        Exception err = null;
        do {
            maxRetries--;
            try {
                runnable.run();
                err = null;
            } catch (Exception e) {
                if(exClass.isAssignableFrom(e.getClass())){
                    err = e;
                }else {
                    throw e;
                }
            }
        } while (err != null && maxRetries > 0);

        if (err != null) {
            throw err;
        }
    }

उपयोग:

    runWithRetry(() -> {
       // do something
    }, TimeoutException.class, 5)

0

सभी आज़माएँ-कैच आपके कार्यक्रम को इनायत से विफल होने की अनुमति देता है। एक कैच स्टेटमेंट में, आप आम तौर पर त्रुटि को लॉग इन करने की कोशिश करते हैं, और हो सकता है कि यदि आवश्यक हो तो परिवर्तन वापस कर दें।

bool finished = false;

while(finished == false)
{
    try
    {
        //your code here
        finished = true
    }
    catch(exception ex)
    {
        log.error("there was an error, ex");
    }
}

क्या आपका मतलब विरोध के रूप में है (!finished)?
सैम मैं कह रहा हूं कि

1
@RohitJain इसे बहुत पसंद करता है while(finished)। मैं अधिक वर्बोज़ संस्करण का उपयोग करना पसंद करता हूं।
सैम मैं कह रहा हूं कि

3
पृथ्वी पर कैसा while(!finished)दिखता है while (finished)??
रोहित जैन

@ रोहित क्योंकि यह केवल एक चरित्र अलग है। वे सभी एक ही चीज के लिए तैयार हो जाते हैं। C # में, मैं एक स्ट्रिंग एक्सटेंशन पद्धति का उपयोग करता हूं IsPopulated()जो सिर्फ !IsNullOrEmpty()यह सुनिश्चित करने के लिए वापस आती है कि मेरा इरादा सभी डेवलपर्स द्वारा समझा गया है।
माइकल ब्लैकबर्न

0

मुझे पता है कि यहां पहले से ही कई समान उत्तर हैं, और मेरा बहुत अलग नहीं है, लेकिन मैं इसे वैसे भी पोस्ट करूंगा क्योंकि यह एक विशिष्ट मामले / मुद्दे से संबंधित है।

जब आपके साथ काम करते facebook Graph APIहैं PHPतो कभी-कभी आपको एक त्रुटि मिलती है, लेकिन तुरंत उसी चीज को फिर से आजमाना एक सकारात्मक परिणाम देगा (विभिन्न जादुई इंटरनेट कारणों के लिए जो इस प्रश्न के दायरे से परे हैं)। इस मामले में कोई जरूरत नहीं है किसी भी त्रुटि ठीक , लेकिन बस फिर से कोशिश करने के लिए क्योंकि किसी प्रकार की "फेसबुक त्रुटि" थी।

फ़ेसबुक सत्र बनाने के तुरंत बाद इस कोड का उपयोग किया जाता है:

//try more than once because sometimes "facebook error"
$attempt = 3;
while($attempt-- > 0)
{
    // To validate the session:
    try 
    {
        $facebook_session->validate();
        $attempt = 0;
    } 
    catch (Facebook\FacebookRequestException $ex)
    {
        // Session not valid, Graph API returned an exception with the reason.
        if($attempt <= 0){ echo $ex->getMessage(); }
    } 
    catch (\Exception $ex) 
    {
        // Graph API returned info, but it may mismatch the current app or have expired.
        if($attempt <= 0){ echo $ex->getMessage(); }
    }
}

इसके अलावा, forलूप काउंट को शून्य से कम करने से ( $attempt--) यह भविष्य में प्रयासों की संख्या को बदलना काफी आसान बनाता है।


0

निम्नलिखित बहुत सरल दृष्टिकोण के साथ मेरा समाधान है!

               while (true) {
                    try {
                        /// Statement what may cause an error;
                        break;
                    } catch (Exception e) {

                    }
                }

1
कृपया @Rohit जैन उत्तर देखें जो कि अधिक विशिष्ट है और नकारात्मक मामलों में अनंत लूप नहीं है।
चंद्र शेखर

0

मुझे यकीन नहीं है कि अगर यह "पेशेवर" करने का तरीका है और मुझे पूरी तरह से यकीन नहीं है कि यह सब कुछ के लिए काम करता है।

boolean gotError = false;

do {
    try {
        // Code You're Trying
    } catch ( FileNotFoundException ex ) {
        // Exception
        gotError = true;
    }
} while ( gotError = true );


0

यहां जावा 8+ के लिए एक पुन: प्रयोज्य और अधिक सामान्य दृष्टिकोण है जिसमें बाहरी पुस्तकालयों की आवश्यकता नहीं है:

public interface IUnreliable<T extends Exception>
{
    void tryRun ( ) throws T;
}

public static <T extends Exception> void retry (int retryCount, IUnreliable<T> runnable) throws T {
    for (int retries = 0;; retries++) {
        try {
            runnable.tryRun();
            return;
        } catch (Exception e) {
            if (retries < retryCount) {
                continue;
            } else {
                throw e;
            }
        }
    }
}

उपयोग:

@Test
public void demo() throws IOException {
    retry(3, () -> {
        new File("/tmp/test.txt").createNewFile();
    });
}

0

शेष समाधानों के साथ मुद्दा यह है कि, संवाददाता फ़ंक्शन बिना किसी अंतराल के बीच-बीच में लगातार कोशिश करता है, इस प्रकार स्टैक पर पानी भर जाता है।

tryसिर्फ हर दूसरे और विज्ञापन अनंत काल में ही क्यों नहीं ?

यहाँ एक समाधान का उपयोग कर setTimeoutऔर एक पुनरावर्ती कार्य:

(function(){
  try{
    Run(); //tries for the 1st time, but Run() as function is not yet defined
  }
  catch(e){
    (function retry(){
      setTimeout(function(){
        try{
          console.log("trying...");
          Run();
          console.log("success!");
        }
        catch(e){
          retry(); //calls recursively
        }
      }, 1000); //tries every second
    }());
  }
})();



//after 5 seconds, defines Run as a global function
var Run;
setTimeout(function(){
  Run = function(){};
}, 5000);

Run()उस फ़ंक्शन या कोड द्वारा फ़ंक्शन को बदलें जिसे आप tryहर सेकंड को फिर से करना चाहते हैं ।


0

स्प्रिंग्स @Retryable एनोटेशन का उपयोग करके इसे आज़माएं, नीचे दी गई विधि 3 प्रयासों के लिए पुनः प्रयास करेगी जब RuntimeException होती है

@Retryable(maxAttempts=3,value= {RuntimeException.class},backoff = @Backoff(delay = 500))
public void checkSpringRetry(String str) {
    if(StringUtils.equalsIgnoreCase(str, "R")) {
        LOGGER.info("Inside retry.....!!");
        throw new RuntimeException();
    }
}

0

नीचे स्निपेट कुछ कोड स्निपेट निष्पादित करता है। यदि आपको कोड स्निपेट निष्पादित करते समय कोई त्रुटि मिली, तो एम मिलीसेकंड और रिट्री के लिए सोएं। संदर्भ लिंक

public void retryAndExecuteErrorProneCode(int noOfTimesToRetry, CodeSnippet codeSnippet, int sleepTimeInMillis)
  throws InterruptedException {

 int currentExecutionCount = 0;
 boolean codeExecuted = false;

 while (currentExecutionCount < noOfTimesToRetry) {
  try {
   codeSnippet.errorProneCode();
   System.out.println("Code executed successfully!!!!");
   codeExecuted = true;
   break;
  } catch (Exception e) {
   // Retry after 100 milliseconds
   TimeUnit.MILLISECONDS.sleep(sleepTimeInMillis);
   System.out.println(e.getMessage());
  } finally {
   currentExecutionCount++;
  }
 }

 if (!codeExecuted)
  throw new RuntimeException("Can't execute the code within given retries : " + noOfTimesToRetry);
}

0

यहां मेरा समाधान कुछ अन्य के समान है जो फ़ंक्शन को लपेट सकता है, लेकिन यदि आप इसे आगे बढ़ाते हैं, तो आप फ़ंक्शन को रिटर्न वैल्यू प्राप्त कर सकते हैं।

    /**
     * Wraps a function with retry logic allowing exceptions to be caught and retires made.
     *
     * @param function the function to retry
     * @param maxRetries maximum number of retires before failing
     * @param delay time to wait between each retry
     * @param allowedExceptionTypes exception types where if caught a retry will be performed
     * @param <V> return type of the function
     * @return the value returned by the function if successful
     * @throws Exception Either an unexpected exception from the function or a {@link RuntimeException} if maxRetries is exceeded
     */
    @SafeVarargs
    public static <V> V runWithRetriesAndDelay(Callable<V> function, int maxRetries, Duration delay, Class<? extends Exception>... allowedExceptionTypes) throws Exception {
        final Set<Class<? extends Exception>> exceptions = new HashSet<>(Arrays.asList(allowedExceptionTypes));
        for(int i = 1; i <= maxRetries; i++) {
            try {
                return function.call();
            } catch (Exception e) {
                if(exceptions.contains(e.getClass())){
                    // An exception of an expected type
                    System.out.println("Attempt [" + i + "/" + maxRetries + "] Caught exception [" + e.getClass() + "]");
                    // Pause for the delay time
                    Thread.sleep(delay.toMillis());
                }else {
                    // An unexpected exception type
                    throw e;
                }
            }
        }
        throw new RuntimeException(maxRetries + " retries exceeded");
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.