Проблема
Я запускаю несколько вызовов какого-либо внешнего метода через ExecutorService . Я хотел бы иметь возможность прерывать эти методы, но, к сожалению, они сами не проверяют флаг прерывания. Можно ли каким-либо образом заставить эти методы вызывать исключение?
Мне известно, что выбрасывание исключения из произвольного местоположения потенциально опасно , в моем конкретном случае я готов воспользоваться этим шансом и готов разобраться с последствиями.
Подробнее
Под «внешним методом» я подразумеваю некоторые методы, которые приходят из внешней библиотеки, и я не могу изменить ее код (ну, я могу, но это сделает его кошмаром обслуживания, когда будет выпущена новая версия).
Внешние методы вычислительно дороги, не связаны с вводом-выводом, поэтому они не реагируют на регулярные прерывания, и я не могу принудительно закрыть канал, сокет или что-то еще. Как я упоминал ранее, они также не проверяют флаг прерывания.
Код концептуально что-то вроде:
// 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()
и подобные методы специальной аннотацией «Interruptable», а затем использовать AspectJ (в котором я, по общему признанию, новичок) для перехвата всех вызовов методов - что-то вроде:
@Before("call(* *.*(..)) && withincode(@Interruptable * *.*(..))")
public void checkInterrupt(JoinPoint thisJoinPoint) {
if (Thread.interrupted()) throw new ForcefulInterruption();
}
Но withincode
не является рекурсивным для методов, вызываемых соответствующими методами, поэтому мне придется редактировать эту аннотацию во внешнем коде.
Наконец, это похоже на мой предыдущий вопрос - хотя заметное отличие состоит в том, что теперь я имею дело с внешней библиотекой.