2016-08-12 1588 views
3

我現在面臨以下警告在NetBeans:Thread.sleep在循環中調用 - 在這種情況下如何防止它(通過重構)?

warning

我知道這是一個常見的問題的人的臉,我發佈前閱讀一些相關的問題。但在這個特定的情況下 - 我在做一個exponential backoff使用Jsoup下載文件 - 我不知道如何防止警告。 我想到了隨着時間的推移計時器,但是......它是最優雅的方式嗎?

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"); 
} 
+0

計時器是一種更優雅的方式。 –

回答

3

雖然Thread.sleep()很少是一個很好的解決方案,但我認爲你的情況是一個例外,因爲它使你的意圖清晰。所以,我會採取@ user1274820的建議來添加一個@SuppressWarnings。但是,這裏是我如何不使用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 
    } 
} 
+0

看起來不錯!但這不是一個積極的等待?我的意思是:'if(future.get()!= null)':當呼叫未完成時,它保持循環。對?似乎是資源消耗,如果它保持循環,直到它是真實的。 –

+0

@LuísSoares否,'future.get()'是一個阻塞調用。它將暫停當前線程,直到可調用完成。 – noscreenname

+0

太棒了!我會稍後測試,然後接受答案。 順便說一句,爲什麼AtomicLong? –

0

遞歸方法調用怎麼樣!!

Document downloadPageAsDocument(String url) throws IOException { 
long waitTime = MILLIS_PER_SECOND; 
if (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); 
     waitTime *= 2; 
     downloadPageAsDocument(url); 
     } 
     catch(IOException ioe) 
     { 

     } 
     catch(StackOverFlowError sfe) 
     { 
      sfe.printStackTrace(); 
     } 
     catch (InterruptedException ex1) { 
     } 

    } 
} 
throw new IOException("I quited after " + (waitTime/MILLIS_PER_SECOND) + " seconds"); 
} 
+0

這可能會導致一個StackOverflowError,經過太多的遞歸調用 – noscreenname

+0

然後將捕獲'StackOverFlowError'加時它達到這個錯誤它將清除堆棧和循環將恢復正常。 – Babel

2

對我來說,它看起來像程序員試圖推動人們使用await/notify方法或TaskScheduling和一些新的方法。

話雖這麼說,你可以無視這樣的警告:

(我不知道它,但我相信這是一個/這兩種)

@SuppressWarnings("SleepWhileHoldingLock") 
@SuppressWarnings("CallToNativeMethodWhileLocked") 

http://hg.netbeans.org/jet-main/rev/1625627adda6

線我發現這個鏈接:

http://netbeans-org.1045718.n5.nabble.com/69cat-editor-New-hint-Thread-sleep-called-in-loop-td3006136.html

+0

thx。這將隱藏警告......但我仍然認爲重構是可能的。 –

相關問題