0

Я хочу, чтобы запустить поток и отменить его, если он не заканчивается в течение 5 секунд:Как прервать поток с учетом объекта Future?

private final class HelloWorker implements Callable<String> { 
    public String call() throws Exception { 
     while(true) { 
      if (Thread.isInterrupted()) { 
       return null; 
      } 
     } 
     return performExpensiveComputation(); 
    } 

    private String performExpensiveComputation() { 
     // some blocking expensive computation that may or may not take a very long time 
    } 
} 

private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize); 
Future<String> future = executorService.submit(new HelloWorker()); 

try { 
    String s = future.get(5, TimeUnit.SECONDS); 
} catch (TimeoutException e) { 
    future.cancel(true); 

    System.out.println("cancelled: " + future.isCancelled() + "done: " + future.isDone()); 

    executorService.shutdown(); 

    try { 
     System.out.println("try to terminate: " + executorService.awaitTermination(60, TimeUnit.SECONDS)); 
    } catch (Exception ex) { 
     // ignore 
    } 
} 

Однако похоже, что awaitTermination возвращает ложь. Есть ли способ проверить, почему служба ExecutorService не будет завершена? Могу ли я выяснить, какие потоки еще запущены?

+0

'future.cancel (true)' фактически прерывает поток. Но это только включает флаг 'thread.isInterrupted()'. Вам нужно будет протестировать его или вспомнить свое 'InterruptedException'. – Gray

+0

в любом случае я могу назвать thread.stop()? – Popcorn

+0

'thread.stop()' устарел. См. Ответ @ Марко. – Gray

ответ

1

Безопасный способ остановки рабочей нити не нарушает стабильности остальной части процесса. Вот почему Thread#stop давно устарел, и почему в Executor Services используется только мягкий кооперативный механизм Thread#interrupt.

Ваш поток должен будет активно проверять, было ли запрошено прерывание и выполнить правильную очистку до окончания. В качестве альтернативы, поток будет вызывать некоторые прерывистые методы JDK, которые будут вызывать InterruptedException, который протектора будет правильно чтить и заканчивать сам.

+0

+1 Вы проверяете бит прерывания чем-то вроде 'while (! Thread.currentThread(). IsInterrupted()))'. – Gray

+0

Что делать, если вычисление, которое выполняет мой поток, блокирует? как я могу активно проверять прерывание в этом случае? Я привел пример HelloWorker, чтобы показать пример. – Popcorn

+1

Это классическая проблема: вы не можете иметь свой торт и съесть его тоже. Если поток принудительно заблокирован против его воли, нет изоляции процесса для защиты всех остальных потоков от повреждения. Если ваш метод вычисления long-runnigg не может быть изменен, чтобы иногда проверять прерванный флаг, тогда вы просто не сможете безопасно остановить поток. –

Смежные вопросы