Java. Остановись задача

21 Ноя
2011

Вот уже почти год как усиленно занимаюсь коддингом на Java. Столкнулся с серией проблем, связанных с многопоточностью, как мне кажется, неразрешимых в рамках текущей реализации jVM от Oracle (сказанное относится к JDK 1.5 и выше).

Казалось бы тривиальная задача: имеем некий Thread (поток), который, мы точно знаем, безнадежно завис, при этом потребляет некоторые ресурсы. Что нам с ним делать? Хотелось бы ресурсы наши освободить. Казалось бы, что проще? Ан нет, при детальном изучении вопроса оказалось, что в jVM просто нет метода, чтобы корректно остановить зависший Thread. Старый метод Thread.stop объявлен Deprecated и предан строжайшей анафеме. Как сказано в javadoc’е это метод «по сути небезопасен». Ну что же, если не безопасен не будем его использовать, дайте нам другой, безопасный метод. Но другого безопасного как ни странно не предлагается. Предлагается, безусловно, очень безопасная инструкция Thread.interrupt(). Но безопасна она, к сожалению, потому, что ровным счетом ничего не делает! Это всего лишь сообщение потоку: «Пожалуйста, остановись». Но если поток данное сообщение проигнорировал то… как сказано в документации «Если поток не отвечает на Thread.interrupt вы можете использовать специфические для вашего приложению трюки». Спасибо, что разрешили. Что называется, крутись как хочешь.

Все становится гораздо запутанней, если задача запущена в пуле потоков. Через, например, ExecutorService.submit(). Казалось бы, мы имеем ссылку на Future, а у Future есть прекрасный метод Future.cancel(boolean), который должен отменить выполнение задачи. Но если задача уже начала выполняться Future.cancel(true) на самом деле не отменит ее. В недрах реализации FutureTask выполняется код:

 if (mayInterruptIfRunning) {
Thread r = runner;
if (r != null)
r.interrupt(); }


Т.е. опять потоку всего лишь рекомендуется прекратить выполнение. Но главный, на мой взгляд недостаток интерфейса Future в том, что он не дает на возможность узнать выполняется ли задача в данный момент. Есть, вроде, метод Future.isDone(), но опять мимо, он возвращает true не только когда задача завершила выполнение, но сразу после вызова Future.cancel(), даже если задача все еще выполняется (ведь Future.cancel() не останавливает задачу которая уже начала выполняться).

Вот, пожалуй и все, что хотел сказать. Очень хотелось бы услышать советы Java программистов практиков о способах остановки зависших потоков и отменой отложенных задач Future.
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх