Проблема
Я запускаю несколько вызовов некоторого внешнего метода с помощью ExecutorService. Я хотел бы иметь возможность прервать эти методы, но, к сожалению, они не проверяют флаг прерывания сами по себе. Есть ли способ заставить исключение быть поднятым из этих методов?
Я знаю, что исключение из произвольного местоположения потенциально опасно, в моем конкретном случае я готов воспользоваться этим шансом и подготовленный для решения последствий.
Подробнее
Посредством "внешнего метода" я подразумеваю некоторый метод (ы), который поступает из внешней библиотеки, и я не могу изменить его код (ну, я могу, но это сделает его кошмаром обслуживания всякий раз, когда выпущена новая версия).
Внешние методы вычисляются дорого, а не IO-bound, поэтому они не реагируют на обычные прерывания, и я не могу принудительно закрыть канал или сокет или что-то еще. Как я уже упоминал ранее, они также не проверяют флаг прерывания.
Код концептуально выглядит как:
// my code
public void myMethod() {
Object o = externalMethod(x);
}
// External code
public class ExternalLibrary {
public Object externalMethod(Object) {
innerMethod1();
innerMethod1();
innerMethod1();
}
private void innerMethod1() {
innerMethod2();
// computationally intensive operations
}
private void innerMethod2() {
// computationally intensive operations
}
}
Что я пробовал
Thread.stop()
теоретически сделает то, что я хочу, но не только он устарел, но также доступен только для реальных потоков, тогда как Я работаю с задачами исполнителя (которые также могут делиться потоками с будущими задачами, например, при работе в пуле потоков). Тем не менее, если не найдено лучшего решения, я конвертирую свой код для использования старомодных потоков вместо этого и использую этот метод.
Другой вариант, который я пробовал, - отметить myMethod()
и подобные методы специальным аннотацией "Прерывание", а затем использовать AspectJ (который я, по общему признанию, новичок), для того, чтобы поймать все вызовы методов там: что-то вроде:
@Before("call(* *.*(..)) && withincode(@Interruptable * *.*(..))")
public void checkInterrupt(JoinPoint thisJoinPoint) {
if (Thread.interrupted()) throw new ForcefulInterruption();
}
Но withincode
не является рекурсивным для методов, вызванных методами сопоставления, поэтому мне пришлось бы отредактировать эту аннотацию во внешний код.
Наконец, это похоже на предыдущий мой вопрос - хотя заметная разница в том, что теперь я имею дело с внешней библиотекой.