В Java можно ли выполнить метод в течение определенного периода времени и остановиться после того, как он достигнет ограничения по времени? - PullRequest
3 голосов
/ 31 мая 2011

У меня есть этот код для загрузки веб-страницы:

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 секунд, я ее остановлю. Я хочу сделать это, потому что моя программа это веб-сканер, и если по ошибке она начинает загружать большой файл, она зависает при загрузке, и это не то, что я хочу делать, так что фильтр загрузки по размеру приветствуется, но, как я не знаю, время фильтра предотвратит эту проблему.

Ответы [ 5 ]

2 голосов
/ 05 апреля 2013

Вы можете использовать AOP и аннотацию @Timeable из jcabi-аспекты (я разработчик):

@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 голосов
/ 31 мая 2011

Правильный способ добиться этого заключается в следующем:

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 голос
/ 31 мая 2011

Жизнь грязная. Если вы хотите привести себя в порядок, нужно немного поработать.

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 голос
/ 31 мая 2011

Существует указанный класс java.util.Timer , предназначенный для выполнения необходимых задач. Вы можете обратиться к API для более подробной информации.

0 голосов
/ 31 мая 2011

Вы не можете остановить запущенный поток.Что вы можете сделать, однако:

1) Создайте новый поток и получите содержимое этого потока.Если поток занимает слишком много времени, чтобы ответить, просто продолжайте и игнорируйте его результаты.Недостаток этого подхода: фоновый поток все равно будет загружать большой файл.

2) Использовать другой API-интерфейс HTTP-соединения с большим количеством элементов управления.Я использовал «Jakarta Commons HttpClient» очень давно и был очень доволен его способностью к таймауту.

...