簡體   English   中英

在Java中,是否可以將方法執行一段時間,達到時間限制后停止?

[英]In Java, is it possible to execute a method for a period of time and stop after it reaches the time limit?

我有這個下載 web 頁面的代碼:

HttpURLConnection connection;

private String downloadContent() {
    InputStream content;
    Source parser;
    try {
        content = connection.getInputStream(); //<--here is the download
        parser = new Source(content);            
        content.close();
        return parser.toString();
    } catch (Exception e) {
        return null;
    }
}

在進行下載時,我試圖獲取下載的數據量,如果達到限制,我會停止下載,但我沒有找到這樣做的方法。 如果有人知道該怎么做,請告訴我。

現在我想限制下載時間。 示例:如果下載通過 20 秒,我停止它。 我想這樣做是因為我的程序是一個網絡爬蟲,如果出現錯誤,它開始下載一個大文件,它會卡在下載中,這不是我想做的,所以歡迎按大小過濾下載,但我不知道,過濾時間會阻止這個問題。

您可以使用來自jcabi-aspects的 AOP 和@Timeable注釋(我是開發人員):

@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String downloadContent() {
  if (Thread.currentThread.isInterrupted()) {
    throw new IllegalStateException("time out");
  }
  // download
}

請注意,您應該定期檢查isInterrupted()並在設置為TRUE時拋出異常。 這是在 Java 中終止線程的唯一方法。

另外,有關更詳細的說明,請查看此帖子: http://www.yegor256.com/2014/06/20/limit-method-execution-time.html

實現這一目標的正確方法如下:

public class TimeOut {

    public static class MyJob implements Callable<String> {

        @Override
        public String call() throws Exception {
            // Do something
            return "result";
        }

    }

    public static void main(String[] args) {

        Future<String> control
                = Executors.newSingleThreadExecutor().submit(new MyJob());

        try {

            String result = control.get(5, TimeUnit.SECONDS);

        } catch (TimeoutException ex) {

            // 5 seconds expired, we cancel the job !!!
            control.cancel(true);

        }
        catch (InterruptedException ex) {

        } catch (ExecutionException ex) {

        }

    }

}

有一個指定的 class java.util.Timer用於執行您需要的任務。您可以參考 API 了解更多詳細信息。

生活很混亂。 如果您想自己清理,則需要一些工作。

private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(20);
private String downloadContent() {
  connection.setConnectTimeout(TIMEOUT); /* Set connect timeout. */
  long start = System.nanoTime(); 
  final InputStream content;
  try {
    content = connection.getInputStream();
  } catch (IOException ex) { 
    return null;
  }
  /* Compute how much time we have left. */
  final long delay = TIMEOUT - 
    TimeUnit.NANOS.toMillis(System.nanoTime() - time); 
  if (delay < 1)
    return null;
  /* Start a thread that can close the stream asynchronously. */
  Thread killer = new Thread() {
    @Override
    public void run() {
      try {
        Thread.sleep(delay); /* Wait until time runs out or interrupted. */
      } catch (InterruptedException expected) { 
        Thread.currentThread().interrupt();
      }
      try {
        content.close();
      } catch (IOException ignore) {
        // Log this?
      }
    }
  };
  killer.start();
  try {
    String s = new Source(content).parser.toString();
    /* Task completed in time; clean up immediately. */
    killer.interrupt();
    return s;
  } catch (Exception e) {
    return null;
  }
}

您無法停止正在運行的線程。 但是,您可以做什么:

1)創建一個新線程並從該線程中獲取內容。 如果線程回答時間過長,只需打開 go 並忽略其結果。 這種方法的缺點:后台線程仍然會下載大文件。

2) 使用另一個 HTTP 連接 API 具有更多控制。 我很久以前就使用過“Jakarta Commons HttpClient”,並且對它的超時能力非常滿意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM