I\'m running multiple invocations of some external method via an ExecutorService. I would like to be able to interrupt these methods, but unfortunately the
I have hacked an ugly solution to my problem. It's not pretty, but it works in my case, so I'm posting it here in case it will help anyone else.
What I did was profile the library parts of my application, hoping that I could isolate a small group of methods which are called repeatedly - for example some get
methods or equals()
or something along these lines; and then I could insert the following code segment there:
if (Thread.interrupted()) {
// Not really necessary, but could help if the library does check it itself in some other place:
Thread.currentThread().interrupt();
// Wrapping the checked InterruptedException because the signature doesn't declare it:
throw new RuntimeException(new InterruptedException());
}
Either inserting it manually by editing the library's code, or automatically by writing an appropriate aspect. Notice that if the library attempts to catch and swallow a RuntimeException
, the thrown exception could be replaced with something else the library doesn't try to catch.
Luckily for me, using VisualVM, I was able to find a single method called a very high number of times during the specific usage I was making of the library. After adding the above code segment, it now properly responds to interrupts.
This is of course not maintainable, plus nothing really guarantees the library will call this method repeatedly in other scenarios; but it worked for me, and since it's relatively easy to profile other applications and insert the checks there, I consider this a generic, if ugly, solution.
If internal methods have similar names, then you could use pointcut definition in xml (spring/AspectJ) instead of annotations so no code modification of the external library should be needed.
Like mhaller said, the best option is to launch a new Process. Since your jobs are not that cooperative, you will never have guarantees on the Thread termination.
A nice solution to your problem would be using a library that supports arbitrary pause/stop of ' lightweight threads' such as Akka instead of the executor service, although this may be a bit of an overkill.
Although I've never used Akka and cannot confirm it works as you expect, the docs state there's a stop() method for stopping actors.
To my knowledge there are two ways of using aspect
AspectJ is a customized compiler which intercepts methods that is compiles (meaning it can't get "external methods". Spring AOP (by default) uses class proxying to intercept methods at runtime (so it can intercept "external methods". but the problem with Spring AOP is that it can't proxy already-proxied classes (which AspectJ can do because it does not proxy classes). I think AspectJ could help you in this case.
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.