简体   繁体   中英

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

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.

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

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

        }

    }

}

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM