在Java中,是否可以在一段时间内执行一个方法并在达到时间限制后停止?

时间:2011-05-30 22:56:33

标签: java time execution

我有这个下载网页的代码:

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,如果出错,它开始下载一个大文件,它会卡在下载中,这不是我想做的,所以欢迎按尺寸下载过滤器,但是我不知道,过滤时间会阻止这个问题。

5 个答案:

答案 0 :(得分: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) {

        }

    }

}

答案 1 :(得分:2)

您可以使用来自@Timeable的AOP和jcabi-aspects注释(我是开发人员):

@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

答案 2 :(得分:1)

有一个指定的类 java.util.Timer ,用于执行您需要的任务。您可以参考API以获取更多详细信息。

答案 3 :(得分: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;
  }
}

答案 4 :(得分:0)

你无法阻止正在运行的线程。但是你能做什么:

1)创建一个新线程并从该线程中获取内容。如果线程需要很长时间才能回答,请继续并忽略其结果。这种方法的缺点:后台线程仍然会下载大文件。

2)使用其他HTTP连接API和更多控件。我很久以前就使用过“Jakarta Commons HttpClient”,对它超时的能力非常满意。