আপনি কীভাবে পুনরায় চেষ্টা চেষ্টা প্রয়োগ করবেন?


203

চেষ্টা-ধরা মানে ব্যতিক্রম পরিচালনার ক্ষেত্রে সহায়তা করা। এর অর্থ একরকম এটি আমাদের সিস্টেমটিকে আরও শক্তিশালী হতে সহায়তা করবে: অপ্রত্যাশিত ঘটনা থেকে পুনরুদ্ধার করার চেষ্টা করুন।

আমরা সন্দেহ করি মৃত্যুদন্ড কার্যকর করার সময় এবং নির্দেশ দেওয়ার সময় (বার্তা প্রেরণে) কিছু ঘটতে পারে, তাই এটি চেষ্টাতে আবদ্ধ হয়ে যায়। যদি এটি প্রায় অপ্রত্যাশিত কিছু ঘটে তবে আমরা কিছু করতে পারি: আমরা ধরাটি লিখি। আমি মনে করি না আমরা কেবল ব্যতিক্রমটি লগ করতে ডেকেছি। আমি বলছি ক্যাচ ব্লকটি আমাদের ত্রুটি থেকে পুনরুদ্ধার করার সুযোগ দেয়।

এখন, আসুন আমরা ত্রুটি থেকে পুনরুদ্ধার করি কারণ আমরা কী ভুল ছিল তা ঠিক করতে পারি। আবার চেষ্টা করে দেখতে দুর্দান্ত লাগতে পারে:

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

এটি দ্রুত চিরন্তন লুপে পতিত হবে, তবে আসুন আমরা বলি যে ফিক্স_স_প্রব্লেম সত্য ফিরে আসে, তারপরে আমরা আবার চেষ্টা করব। জাভাতে তেমন কোনও জিনিস নেই বলে আপনি কীভাবে এই সমস্যার সমাধান করবেন? এটি সমাধানের জন্য আপনার সেরা ডিজাইন কোডটি কী হবে?

এটি একটি দার্শনিক প্রশ্নের মতো, প্রদত্ত যেটি আমি ইতিমধ্যে জানি যা আমি চাই তা সরাসরি জাভা দ্বারা সমর্থিত নয়।


5
এটি কোন ধরণের ব্যতিক্রম?
ভেশে গুরুং

23
যদিও আপনার ব্যতিক্রমটির নামটি আমি পছন্দ করি। ;)
রোহিত জৈন

কৃতজ্ঞতায়, এমন অনেকগুলি ব্যতিক্রম নেই যা থেকে আপনি পুনরুদ্ধার করতে পারেন। আমি স্বীকার করি যে আমার প্রাথমিক অনুপ্রেরণাটি সত্যিকারের ব্যতিক্রম ছিল না, তবে এটি কখনই ঘটে না সেটিকে এড়ানোর উপায়: আমি remove()একটি থেকে চেষ্টা করি java.util.Queue, যেটি বজায় থাকে এবং InvalidElementExceptionযখন সারিটি খালি থাকে। এটি খালি কিনা জিজ্ঞাসার পরিবর্তে, আমি চেষ্টা-এর মধ্যে ক্রিয়াগুলি ঘিরে রাখি (যা সম্মতিতে পূর্ববর্তী থাকলেও বাধ্যতামূলক হয়ে যায়)। এই জাতীয় ক্ষেত্রে, catchব্লকে আমি আরও উপাদানগুলির সাথে সারিটি পুনরায় পূরণ করতে বলব এবং তারপরে পুনরায় চেষ্টা করুন। Voila।
আন্দ্রেস ফারিয়াস

1
আমি দেখতে পাচ্ছি যে এটি করার স্বাভাবিক উপায়টি হবে ডিবি অ্যাক্সেসের জন্য, যদি সংযোগটি পুনরায় সংযোগ করতে ব্যর্থ হয়, যদি এটি ব্যর্থ হয় তবে বড় ব্যতিক্রম ছুঁড়ে ফেলুন অন্যথায় কলটি আবার চেষ্টা করুন। যেমন বলা হয়েছে আমরা নীচে চেক সহ একটি লুপে এটি করতে পারি যদি (ত্রুটি <> 0) তবে ফিরে যান অন্যথায় বিরতি;
থেরেসা ফারস্টার

উত্তর:


303

আপনার নিজের লুপটির 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
@ এন্ড্রেসফারিয়াস .. হ্যাঁ, এই উত্তরের সবচেয়ে গুরুত্বপূর্ণ বিষয়টি হ'ল একটি অন্তর্ভুক্ত করা maxTries। অন্যথায় এটি একটি চলতে থাকবে infinite loopযদি ব্যবহারকারী ক্রমাগত ভুল ইনপুট দেয় এবং তাই প্রস্থান করবে না। যদিও আপনাকে স্বাগতম। :)
রোহিত জৈন

এর জন্য আপনাকে ধন্যবাদ - এটি কিছু খুব গাn় কোড লেখা থেকে আমাকে বাঁচিয়েছে!
ডেভিড হলিডে

2
এখানেই ক্যাচের ভিতরে থ্রেড.স্লিপ () ফাংশন যুক্ত করা কি সম্ভব? কারণ কিছু ক্ষেত্রে সেলেনিয়াম লাইব্রেরিতে পৃষ্ঠার প্রতিক্রিয়ার জন্য অপেক্ষা করা যা সমালোচনা হয়ে ওঠে। ধন্যবাদ।
স্যাত আতান পিএইচডি

2
দুর্দান্ত কাজ! নতুনদের জন্য: আপনি যদি ইতিবাচক অসীম লুপ পান তবে আপনি "বিরতি" যুক্ত করেছেন কিনা তা পরীক্ষা করে দেখুন; "চেষ্টা" ব্লক শেষে।
ক্রিজিসটোফ ওয়ালকজেসউস্কি

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
প্রদত্ত অন্যান্য উত্তরের মতো শেষবারের চেষ্টাটি ব্যর্থ হলে আপনার ব্যতিক্রমটি আবার ছুঁড়ে ফেলা উচিত।
সিভ্যাকা

35

যথারীতি, সেরা নকশা নির্দিষ্ট পরিস্থিতিতে নির্ভর করে। সাধারণত যদিও আমি কিছু লিখি:

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

অপেক্ষা করুন, লুপ ঘোষণার জন্য যেমন শর্ত থাকে না কেন: (int retry = 0; retry <6; retry ++) ??
দিদিয়ার এ।

8
কারণ আমি কেবল সর্বশেষ প্রয়াসে ফেলে দিতে চাই, এবং তাই ক্যাচ ব্লকের সেই শর্তটি প্রয়োজন, এটি শর্তকে অপ্রয়োজনীয় হিসাবে তৈরি করে।
মেরিটন

1
আমি মনে করি না যে continueসেখানে প্রয়োজন আছে .. এবং আপনি কেবল যদি শর্তটি ফ্লিপ করতে পারেন।
Koray Tugay

19

যদিও try/catchমধ্যে whileসুপরিচিত এবং ভালো কৌশল আমি তোমাকে recursive কল সুপারিশ করতে চান:

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
এই ব্যবহারের ক্ষেত্রে লুপের চেয়ে পুনরাবৃত্তি কীভাবে ভাল?
ড্যান

7
স্ট্যাক ট্রেসটি এটির জন্য কিছুটা অদ্ভুত লাগতে পারে, কারণ এটি limitপুনর্বার পদ্ধতিটি গণনা না করে ? লুপ সংস্করণটির বিপরীতে, যা 'আসল' স্তরে ফেলে দেবে ...
ক্লকওয়ার্ক-মিউজিক

7
অবশ্যই কাগজে মার্জিত দেখায় তবে আমি নিশ্চিত নই যে পুনরাবৃত্তিটি কোনওভাবে সঠিক পন্থা।
টমাস

3
আমি এখানে বুঝতে পারি না কেন এখানেও পুনরাবৃত্তি হয়। যাই হোক, আমি মনে করি এটি সরলীকৃত করা যেতে পারে:void retry(int times) { (...) if (times==0) throw w; retry(times--);
sinuhepop

8
কেবল পুনরাবৃত্তির বিকল্প হিসাবে পুনরাবৃত্তিটি ব্যবহার করা খারাপ অভ্যাস। পুনর্বারণটি ব্যবহারের জন্য যখন আপনি কিছু ডেটা পুশ এবং পপ করতে চান।
লার্নের মারকুইস

19

আপনার সঠিক দৃশ্যটি ব্যর্থতাফের মাধ্যমে পরিচালিত :

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

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

বেশ সহজ.


5
খুব সুন্দর গ্রন্থাগার
মাকসিম

ঐ ভাবছি, আপনি আপনার gradle নির্ভরতা এই প্রয়োজন হবে - কম্পাইল '1.1.0 net.jodah: failsafe'
Shreyas

18

আপনি জেবিবি দিক থেকে এওপি এবং জাভা টিকা ব্যবহার করতে পারেন (আমি বিকাশকারী):

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

আপনি ব্যবহার করতে পারেন @Loggableএবং @LogExceptionটীকাগুলিও।


কি দারুন ! শোনাচ্ছে অভিনব! :)
আলিন্দ বিলোর 21

শীর্ষ উত্তর হওয়া উচিত।
মোহাম্মদ তাহের আলরেফাই

2
চেষ্টা ব্যর্থ হলে ত্রুটিটি "সমাধান" করার কোনও উপায় আছে (এমন কিছু গ্রহণ যা পরবর্তী প্রচেষ্টা ঠিক করতে পারে)? : প্রশ্ন দেখতে পাবেন fix_the_problem();ধরা ব্লক মধ্যে
warch

খোলা ইস্যুগুলির পরিমাণ এবং স্বীকৃত বাগগুলি নির্ধারিত না হওয়ার জন্য সময় নির্ধারণ করে, আমি এই লাইব্রেরিতে নির্ভর করব না।
মাইকেল Lihs

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
পছন্দ করুন আপনি পারেন if (tryCount < max) fix()- তবে এটি একটি সাধারণ পদ্ধতির ফর্ম্যাট; বিবরণ একটি নির্দিষ্ট ক্ষেত্রে উপর নির্ভর করবে। আমি দেখছি একটি পেয়ারা ভিত্তিক রিট্রিয়ারও রয়েছে।
স্টিফেন পি

4

স্প্রিং এওপি এবং টীকা ভিত্তিক সমাধান:

ব্যবহার (কাজের @RetryOperationজন্য আমাদের কাস্টম টীকা):

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

এটি সম্পাদন করার জন্য আমাদের দুটি জিনিস প্রয়োজন হবে: ১. একটি টীকা ইন্টারফেস এবং ২ একটি বসন্ত দিক। এগুলি বাস্তবায়নের জন্য এখানে একটি উপায়:

টীকাগুলি ইন্টারফেস:

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
কোডটি যদি ব্যর্থ হয় তবে আসল ব্যতিক্রমটি ছুঁড়ে ফেলা উচিত
লিল্লিনাক্স

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
}

নিচে ভোটাররা কেন মতামত জানান, ধন্যবাদ!
রজারডপ্যাক 20 '

1
এটি হ্রাস করা এবং কোনও কারণ উল্লেখ না করার জন্য এটি নিছক অজ্ঞতা।
এক্সপ্লোররাজ

ঘুমের সেখানে সুস্পষ্ট যেহেতু সময় লুপ অপেক্ষা করবেন কি করবে না
জোয়াও মধ্যে Pimentel ফেরেইরা

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
@ রোহিতজাইন এটি দেখতে অনেক বেশি পছন্দ করে while(finished)। আমি আরও ভার্বোজ সংস্করণ ব্যবহার করতে পছন্দ করি।
স্যাম আমি বলছি মনিকা পুনরায়

3
পৃথিবীতে while(!finished)কেমন দেখাচ্ছে while (finished)??
রোহিত জৈন

@ রোহিত কারণ এটি কেবলমাত্র একটি চরিত্রের থেকে আলাদা। তারা সবাই একই জিনিস সংকলিত হয়। সি # তে, আমি একটি স্ট্রিং এক্সটেনশন পদ্ধতি ব্যবহার করি 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
দয়া করে @ রোহিত জৈন উত্তর দেখুন যা আরও নির্দিষ্ট এবং নেতিবাচক ক্ষেত্রে অসীম লুপ নয়।
চন্দ্র শেখর

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

স্প্রিংস @ পুনরায় ব্যবহারযোগ্য টীকাগুলি ব্যবহার করে চেষ্টা করুন, রানটাইম এক্সেকশন হওয়ার সময় নীচের পদ্ধতিটি 3 টি চেষ্টা করে আবার চেষ্টা করবে

@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");
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.