2011-05-30 70 views
3

我有這樣的代碼,下載一個網頁:在Java中,是否可以執行一段時間的方法並在達到時間限制後停止?

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秒,我停止它。我想這樣做是因爲我的程序是一個webcrawler,如果由於錯誤,它開始下載一個大文件,它會停留在下載中,並不是我想要做的,所以按照大小下載過濾器是受歡迎的,但我不知道,過濾時間可以防止這個問題。

+0

通常這樣做是通過**設置超時**。什麼是連接對象? – mre 2011-05-30 23:03:02

+1

我打算回答,但其他人會回答。答案包括創建一個線程來讀取數據,並在超時後中斷或關閉連接返回的數據流。 – 2011-05-30 23:03:25

+0

你在使用什麼庫?它應該爲你提供一個超時方法。 – 2011-05-30 23:05:12

回答

2

正確的方式實現這一目標是:

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) { 

     } 

    } 

} 
+0

現在我覺得很蠢。我在我的程序中有一段精確的代碼,但我從來沒有意識到我可以用它來做我想做的事情。我會測試。 – 2011-05-31 01:59:01

+2

與此相關的問題是後臺任務通常不會被取消。它將繼續運行。該任務及其使用的任何方法必須是可中斷的。特別是,在I/O的情況下,您必須使用正確配置的「InterruptibleChannel」。 – erickson 2011-05-31 02:20:11

0

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

1)創建一個新的線程,並從該線程獲取內容。如果線程花費很長時間回答,只需繼續並忽略其結果。這種方法的缺點:後臺線程仍然會下載大文件。

2)使用另一個帶有更多控件的HTTP連接API。我很久以前就使用了「Jakarta Commons HttpClient」,並對它的超時能力感到非常滿意。

+0

雅加達提供了一些關於下載的大小? – 2011-05-30 23:09:32

+2

Thread.interrupt()? – Neil 2011-05-30 23:23:21

1

存在指定的類java.util.Timer中是打算做的任務,你required.You可以參考API更多詳情。

+0

計時器允許你選擇開始的時刻,但沒有幫助OP的請求... – JVerstry 2011-05-31 02:04:47

+0

我不知道你的「OP的要求」是什麼意思?但是什麼時候開始取決於你,你可以在你想要的任何開始點指定它。 – Vacker 2011-06-02 12:39:48

+0

OP =原始文章 – JVerstry 2011-06-02 16:35:47

1

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

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

您可以使用AOP和jcabi-aspects一個@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

相關問題