Luís Soares Luís Soares - 3 months ago 17
Java Question

Thread.sleep called in loop - how to prevent it in this case (by refactoring)?

I'm facing the following warning in NetBeans:

warning

I know this is a common issue people face and I read some related questions before posting. But in this specific case - where I'm doing an exponential backoff to download a document using Jsoup - I'm not sure how to prevent the warning.
I thought about a timer with increasing time, but... is it the most elegant way?

Document downloadPageAsDocument(String url) throws IOException {
long waitTime = MILLIS_PER_SECOND;
while (waitTime < MILLIS_PER_HOUR) {
try {
return Jsoup.connect(url).timeout(REQ_TIMEOUT_MILLISECONDS).get(); // an IOException is thrown on timeout by Jsoup
} catch (IOException ex) {
log.log(Level.WARNING, "{0}... wating {1} seconds", new Object[]{ex.getMessage(), (waitTime / MILLIS_PER_SECOND)});
try {
Thread.sleep(waitTime);
} catch (InterruptedException ex1) {
}
waitTime *= 2;
}
}
throw new IOException("I quited after " + (waitTime / MILLIS_PER_SECOND) + " seconds");
}

Answer

While a Thread.sleep() is rarely a good solution, I think your case is an exception, because it makes your intention clear. So, I'd take @user1274820 advice to add a @SuppressWarnings. However, here is how I would do this without using Thread.sleep()

static ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);

Document downloadPageAsDocument(String url) throws IOException {
    AtomicLong waitTime = new AtomicLong(MILLIS_PER_SECOND);
    try {
        while (waitTime.get() < MILLIS_PER_HOUR) {
            System.out.println("iteration wait=" + waitTime.get());
            ScheduledFuture<String> future = exec.schedule(() -> {
                try {
                    return jsoupCall();
                } catch (IOException ex) {
                    waitTime.getAndUpdate((l) -> l * 2);
                }
                return null;
            }, waitTime.get(), TimeUnit.MILLISECONDS);
            if (future.get() != null) { // wait for completion
                break; //break if jsoupCall was successful
            }
        }
    } catch (InterruptedException | ExecutionException e) {
        // handle exceptions
    }
}
Comments