Ограничение по времени для отдельных потоков с помощью ExecutorService
У меня есть ExecutorService, управляющая несколькими Callables. Задачи, которые запускаются Callables, - это, в основном, преобразования черного ящика и хруст числа. При определенных условиях преобразуемые данные будут колебаться, и нить займет более часа. Для сравнения, большинство потоков завершено в течение минуты.
Было установлено, что данные из длинных потоков не являются релевантными. Я хотел бы прервать любой поток, который длится дольше определенного времени. Каким будет лучший способ сделать это?
Ответы
Ответ 1
Используйте ScheduleExecutorService для планирования задачи до taskFuture.cancel(true)
задачи, выполняемой в течение длительного времени, когда достигается тайм-аут. Если задача завершится до этого, она не будет отменена.
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){
final Future<T> future = service.submit(c);
canceller.schedule(new Callable<Void>(){
public Void call(){
future.cancel(true);
return null;
}
}, timeoutMS, TimeUnit.MILLI_SECONDS);
return future;
}
Ответ 2
Вы можете отменить будущее и т.д., как и в других ответах, но вам нужно убедиться, что ваши потоки, которые являются "числовыми хрустами", могут обрабатывать прерывание и законно заканчиваться. Вы говорите, что это операция черного ящика - насколько вы уверены, что прерванный статус потока активно проверяется в черном ящике? Если это не так, вы не можете отменить его с прерыванием. Черный ящик должен быть написан с перерывом в памяти.
Ответ 3
Лучший способ сделать это - представить еще одного Исполнителя. Вы можете использовать ScheduledExecutorService для отмены всех длительно работающих задач, например:
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newScheduledThreadPool(1);
public void executeTask(Callable<?> c){
final Future<?> future = service.submit(c);
canceller.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, SECONDS_UNTIL_TIMEOUT, TimeUnit.SECONDS);
}
Ответ 4
Вы можете получить список ваших соответствующих фьючерсов (которые создаются при отправке Callable) вместе со временем его запуска.
Другая задача может быть проверена каждую минуту, если есть какая-то задача, выполняемая в течение более определенного времени, и если да, вызовите отмену (истину) в будущем. Готовые фьючерсы будут удалены из списка.
Ответ 5
Вы можете использовать этот метод
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
throws InterruptedException
и установите максимальный тайм-аут на одну минуту. Если ваш поток занимает больше, чем просто, он просто прерван.