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

Posted

技术标签:

【中文标题】在Java中,是不是可以将方法执行一段时间并在达到时间限制后停止?【英文标题】:In Java, is it possible to execute a method for a period of time and stop after it reaches the time limit?在Java中,是否可以将方法执行一段时间并在达到时间限制后停止? 【发布时间】:2011-05-30 22:56:33 【问题描述】:

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

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 秒,我停止它。我想这样做是因为我的程序是一个网络爬虫,如果出现错误,它开始下载一个大文件,它会卡在下载中,这不是我想做的,所以欢迎按大小过滤下载,但我不知道,过滤时间会阻止这个问题。

【问题讨论】:

通常这是通过设置超时来完成的。 connection 对象是什么? 我打算回答它,但其他人会。答案涉及创建一个线程来读取数据并在超时后中断它或关闭连接返回的流。 你用的是什么库?它应该为你提供一个超时方法。 连接是 HttpURLConnection。目前我有多种这些方法同时运行,每一个都在一个线程中。 【参考方案1】:

实现这一点的正确方法如下:

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) 

        

    


【讨论】:

我现在觉得自己很笨。我的程序中有这段与其他东西完全相同的代码,但我从未意识到我可以用它来做我想做的事。我会测试。 这样做的问题是后台任务通常不会被取消。它将继续运行。任务及其使用的任何方法都必须是可中断的。具体来说,在 I/O 的情况下,您必须使用正确配置的 InterruptibleChannel【参考方案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

【讨论】:

【参考方案3】:

有一个指定的类 java.util.Timer 旨在完成您需要的任务。您可以参考 API 了解更多详细信息。

【讨论】:

定时器允许你选择开始的时刻,但对OP的请求没有帮助...... 我不知道您的“OP 的要求”是什么意思?但是什么时候开始取决于你,你可以在任何你想要的开始点指定它。【参考方案4】:

生活一团糟。如果你想自己打扫卫生,这需要一些工作。

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】:

您无法停止正在运行的线程。但是,您可以做什么:

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

2) 使用另一个具有更多控件的 HTTP 连接 API。我很久以前就使用过“Jakarta Commons HttpClient”,对它的超时功能非常满意。

【讨论】:

Jakarta 提供了有关下载大小的信息?

以上是关于在Java中,是不是可以将方法执行一段时间并在达到时间限制后停止?的主要内容,如果未能解决你的问题,请参考以下文章

显示使用延迟作业一段时间后运行的方法

如何在Java中包含多个方法?枚举不是正确的方法吗?

java动态代理

父线程 在创建了子线程后,是否继续执行自己的代码?它可以在子线程结束前 结束吗?

智能合约不断听取价格信息并在达到价格后立即执行的最佳方式是啥?

排队等待一段时间后执行的动作(不是效果)。