问题
I have this code that downloads a web page:
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;
}
}
While doing the download, I tried to get the amount of downloaded data, and if it reaches a limit, I stop the downloading, but I not found a way to do this. If someone know how to do, please tell me.
Now I want to limit the download time. Example: if the download pass 20 seconds, I stop it. I want to do this because my program it's an webcrawler and if by an error, it begins downloading a big file, it will stuck in the download, and is not this I want to do, so a filter in download by size is welcome, but as I don't know, a filter time will prevent this problem.
回答1:
The proper way to achieve this is the following:
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) {
}
}
}
回答2:
You can use AOP and a @Timeable annotation from jcabi-aspects (I'm a developer):
@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String downloadContent() {
if (Thread.currentThread.isInterrupted()) {
throw new IllegalStateException("time out");
}
// download
}
Pay attention that you should check for isInterrupted()
regularly and throw an exception when it is set to TRUE
. This is the only way to terminate a thread in Java.
Also, for more detailed explanation, check this post: http://www.yegor256.com/2014/06/20/limit-method-execution-time.html
回答3:
There is a specified class java.util.Timer that is intended to do the tasks you required.You can reference the API for more detail.
回答4:
Life is messy. If you want to clean up after yourself, it takes some work.
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;
}
}
回答5:
You can't stop a running thread. What you can do, however:
1) Create a new thread and fetch the content from this thread. If the thread takes too long to answer, just go on and ignore its results. Downside of this approach: the background thread will still download the big file.
2) Use another HTTP connection API with more controls. I've used "Jakarta Commons HttpClient" a long time ago and was very pleased with its ability to timeout.
来源:https://stackoverflow.com/questions/6181420/in-java-is-it-possible-to-execute-a-method-for-a-period-of-time-and-stop-after