I'm running multiple invocations of some external method via an ExecutorService. I would like to be able to interrupt these methods, but unfortunately they do not check the interrupt flag by themselves. Is there any way I can force an exception to be raised from these methods?
I am aware that throwing an exception from an arbitrary location is potentially dangerous, in my specific case I am willing to take this chance and prepared to deal with the consequences.
By "external method" I mean some method(s) that come from an external library, and I cannot modify its code (well I can, but that will make it a maintenance nightmare whenever a new version is released).
The external methods are computationally expensive, not IO-bound, so they don't respond to regular interrupts and I can't forcefully close a channel or a socket or something. As I've mentioned before, they also do not check the interrupt flag.
The code is conceptually something like:
// 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()
will theoretically do what I want, but not only is it deprecated but it is also only available for actual threads, while I'm working with executor tasks (which might also share threads with future tasks, for example when working in a thread pool). Nevertheless, if no better solution is found, I will convert my code to use old-fashioned Threads instead and use this method.
Another option I've tried is to mark myMethod()
and similar methods with a special "Interruptable" annotation and then use AspectJ (which I am admittedly a newbie at) for catching all method invocations there - something like:
@Before("call(* *.*(..)) && withincode(@Interruptable * *.*(..))") public void checkInterrupt(JoinPoint thisJoinPoint) { if (Thread.interrupted()) throw new ForcefulInterruption(); }
But withincode
isn't recursive to methods called by the matching methods, so I would have to edit this annotation into the external code.
Finally, this is similar to a previous question of mine - though a notable difference is that now I'm dealing with an external library.
The following weird ideas come to my mind:
This solution isn't easy either, but it could work: Using Javassist or CGLIB, you can insert code at the beginning of each internal method (the ones presumably being called by the main run() method) to check if the thread is alive, or some other flag (if it's some other flag, you'll have to add it as well, along with a method to set it).
I'm proposing Javassist/CGLIB instead of extending the class through code because you mention it's external and you don't want to change the source code, and it may change in the future. So adding the interrupt checks at runtime will work for the current version and also in future versions even if the internal method names change (or their parameters, return values, etc). You just have to take the class and add interrupt checks at the beginning of each method that is not the run() method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With