Search code examples
javatimeoutclosuresthreadpoolexecutorcancellation

Does a Java try catch use a closure to catch terminating child threads while the parent thread is blocked?


I am looking for an expansion of the question asked here: Does a Future timeout kill the Thread execution

Given the following code snippet, I am curious to know if the catch for TimeoutException will catch threads that exceed the timelimit in some kind of closure? Will these catch even when the main thread is being blocked by awaitTermination()? This implementation seems to work. ...but it may be that I have simply been lucky so far to have no deadlocks and no apparent race conditions.

public List<T> setupThreads() throws InterruptedException, ExecutionException {
    if (nThreads < 1 || timeout < 1 || preRunObjects == null || preRunObjects.isEmpty()) {
        return null;
    }
    List<T> postRunObjects = new ArrayList<>();
    List<Future<T>> futures = new ArrayList<>();
    ExecutorService executor = Executors.newFixedThreadPool(nThreads);
    for (T runMe : preRunObjects) {
        futures.add(executor.submit(runMe));
    }
    for (Future<T> f : futures) {
        try {
            postRunObjects.add(f.get(timeout, TimeUnit.SECONDS));
        } catch (TimeoutException te) {
            log.warn("A thread has failed to run in time! It will be canceled.");
            if(!f.isDone()) {
                f.cancel(true);
                if(f.isCancelled()) {
                    log.info("Punishment complete!");
                }
            }
        }
    }
    executor.shutdown();
    executor.awaitTermination((timeout * postRunObjects.size()), TimeUnit.SECONDS);
    return postRunObjects;
}

Solution

  • I am curious to know if the catch for TimeoutException will catch threads that exceed the timelimit in some kind of closure? Will these catch even when the main thread is being blocked by awaitTermination()?

    In some kind of closure? Would it matter?

    Your main thread does not call executor.awaitTermination() until after the for(...) loop has completed.

    Also note: All of the f.get() calls are sequential: Your main thread will wait up to timeout seconds for the first result, and then it will wait up to timeout more seconds for the next result, ...and the next, ...and the next, ...and so on.

    Is that what you had in mind? Or did you mean to wait no longer than timeout total seconds?