A trick for adding timeouts to methods that weren't designed to handle timeouts is to use a thread pool. A thread pool allows you to execute tasks and wait for them for a certain duration. Of course, it means that you will block the calling thread, but you will block it for a certain amount of time:
return threadPool.submit(() -> { // execute your logic }).get(10, TimeUnit.SECONDS);
This code will compute some value or throw TimeoutException if it lasts for more than 10 seconds. Wrapping any code inside such a block will allow you to handle a timeout for any sort of code. However, this doesn't mean that the wrapped code ends after 10 seconds; it just means that the caller doesn't wait for it anymore. The ...