Java future timeout with way to cleanup

347 Views Asked by At

Say I have a method getCloseableResource() which might take an unbounded amount of time to complete and returns something that needs to be closed or cleaned up.

I want to submit a task to an executorService to get the closeable resource but only wait a limited amount of time.

Future<CloseableResource> crFuture = executorService.submit(() -> getCloseableResource());
CloseableResource cr = crFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
catch (TimeoutException e) {
  // abandon the attempt
}

The problem is that if I abandon waiting, I'll never be able to close the resource since I won't have a handle to it and the resource will never get cleaned up properly.

Is there some mechanism to specify cleanup code to execute when getCloseableResource returns so that I can abandon waiting for it AND make sure it is disposed of cleanly? Or maybe there is a more advance construct rather than an executor service.

2

There are 2 best solutions below

0
On

I think one solution is to submit a task that has some state that keeps track of whether the request was abandoned. When the resource is retrieved the executor thread can check if the main thread had abandoned it and if so, close the resource. In the main thread, if the the timeout occurs and you want to abandon the resource, just set the abandoned flag. All of this would need to be written in a thread safe way of course.

2
On

You can submit another task in the timeout case that closes the resource once it has been allocated:

Future<Closeable> crFuture = executorService.submit(this::getCloseableResource);
try {
    Closeable cr = crFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
    // ...
} catch (TimeoutException e) {
    executorService.submit(() -> {
        try {
            crFuture.get().close();
        } catch (IOException | InterruptedException | ExecutionException ex) {
            // ...
       }
    });
}