ExecutorService that interrupts tasks after a timeout
ExecutorService, прерывающий задачи по истечении времени ожидания
Я ищу реализацию ExecutorService, которой может быть предоставлен тайм-аут. Задачи, отправленные в ExecutorService, прерываются, если для их выполнения требуется больше времени, чем время ожидания. Реализация такого чудовища не такая уж сложная задача, но мне интересно, знает ли кто-нибудь о существующей реализации.
Вот что я придумал на основе некоторых обсуждений ниже. Есть комментарии?
Для этого вы можете использовать ScheduledExecutorService. Сначала вы должны отправить его только один раз, чтобы начать немедленно и сохранить созданное будущее. После этого вы можете отправить новую задачу, которая отменит сохраненное будущее через некоторый промежуток времени.
Это выполнит ваш обработчик (основную функциональность, которая будет прервана) на 10 секунд, затем отменит (т. Е. прервет) эту конкретную задачу.
Ответ 2
К сожалению, решение является ошибочным. В ScheduledThreadPoolExecutorэтом вопросе также сообщается об ошибке: отмена отправленной задачи не освобождает полностью ресурсы памяти, связанные с задачей; ресурсы освобождаются только по истечении срока действия задачи.
Таким образом, если вы создаете TimeoutThreadPoolExecutor с довольно длительным сроком действия (типичное использование) и отправляете задачи достаточно быстро, вы в конечном итоге заполняете память, даже если задачи фактически завершены успешно.
Вы можете увидеть проблему в следующей (очень грубой) тестовой программе:
publicstaticvoidmain(String[] args)throws InterruptedException { ExecutorServiceservice=newTimeoutThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS, newLinkedBlockingQueue<Runnable>(), 10, TimeUnit.MINUTES); //ExecutorService service = Executors.newFixedThreadPool(1); try { finalAtomicIntegercounter=newAtomicInteger(); for (longi=0; i < 10000000; i++) { service.submit(newRunnable() { @Override publicvoidrun() { counter.incrementAndGet(); } }); if (i % 10000 == 0) { System.out.println(i + "/" + counter.get()); while (i > counter.get()) { Thread.sleep(10); } } } } finally { service.shutdown(); } }
Программа исчерпывает доступную память, хотя и ожидает завершения созданных Runnable задач.
Я думал об этом некоторое время, но, к сожалению, не смог придумать хорошего решения.
Обновить
Я обнаружил, что об этой проблеме сообщалось как об ошибке JDK 6602600, и, похоже, она была исправлена в Java 7.
Ответ 3
Завершите задачу в FutureTask, и вы можете указать время ожидания для FutureTask. Посмотрите на пример в моем ответе на этот вопрос,
После тонны времени на опрос, наконец, я использую invokeAll метод ExecutorService для решения этой проблемы. Это будет строго прерывать выполнение задачи во время выполнения задачи. Вот пример