问题描述
|
我有以下代码可下载网页:
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秒,我将停止它。我要执行此操作是因为我的程序是一个网络爬虫,如果出现错误,它将开始下载一个大文件,它将卡在下载中,不是我想要这样做,因此请按大小过滤下载是欢迎的,但我不知道,过滤时间可以避免此问题。
解决方法
实现此目的的正确方法如下:
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) {
}
}
}
, 您可以在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
, 有一个指定的类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)创建一个新线程,并从该线程中获取内容。如果线程回答所需的时间太长,请继续并忽略其结果。这种方法的缺点:后台线程仍将下载大文件。
2)使用具有更多控件的另一个HTTP连接API。我很早以前就使用过“ Jakarta Commons HttpClient”,并且对其超时功能感到非常满意。