I programmed a sudoku solver in Java for a homework, and I am currently trying to figure out the problematic inputs it can face to make it better. I have generated a few thousand sudoku grids with David Bau's sudoku generator, and now I am running my program against them.
The problem is that while most of them complete in very reasonable times, some of them prove to be problematic and make my algorithm search like crazy until I run out of heap space. So I thought I should offshore the solving job to a secondary thread and run it with a timeout. Right now, I'm using a thread 'pool' of one thread (in the form of an ExecutorService
) and I'm submitting Callable
s to it. I then try to get the value with a timeout:
Callable<Long> solveAndReturnTime = new Callable<Long>() { /* snip */ };
Future<Long> time = executor.submit(solveAndReturnTime);
try
{
long result = time.get(10, TimeUnit.SECONDS);
System.out.printf("%d millis\n", result);
}
catch (TimeoutException e)
{
System.err.println("timed out");
time.cancel(true);
}
My problem is that apparently, one does not simply cancel a Future
in Java. Future<T>.cancel(boolean)
apparently doesn't interrupt the task right away. Because of that, the pool is stuck with carrying an undying task, and the subsequent attempts timeout because they never get a chance to run.
Adding more threads to the pool is not an option because I run on limited cores and if too many tasks obstinately run, the legitimate ones will be unfairly slowed down. I also don't want the overhead of frequently checking if the task was aborted from my main algorithm.
How can I abruptly, mercilessly and brutally terminate a task? I'm open to anything that will let me recover on the main thread.
EDIT My algorithm is completely sequential, uses no global object, and contains no lock. As far as I can tell, nothing will go wrong if the task is cancelled at a random moment; and even if it does, it's not production code. I'm ready to walk the dangerous and treacherous walk for this one.
Just as in any other language methods to mercifully terminate a thread are Deprecated or not recommended. Because such methods may cause deadlocks (a thread being terminated will not release the locks it's holding).
The correct solution to the problem is having an additional check for Thread.currentThread ().isInterrupted ()
on every iteration of the main cycle in you Callable. So when the thread is being interrupted it would see it and gracefully shut down.
And since it's you code running in another thread it shouldn't be difficult for you to modify it.
In addition to Andrei's answer, which is correct, you should be aware that doing this work in a thread will not protect your application from running out of memory via an OOM. If your worker thread consumes the entire heap, the main thread can very well die too.
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