<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
I am not familiar with Helidon’s internals or with the details of the particular issue, but you can separate the “idle” and “busy” threads by spawning them in different ExecutorServices. For example, threads that wait an accept new requests are spawned in one
 ES and they, in turn, spawn a “request processing” thread in another. To shut down the server you will then forcefully shut down the first ES, stopping new requests from being accepted, and gracefully shut down the second, giving the requests some time to
 finish.
<div class=""><br class="">
</div>
<div class="">— Ron<br class="">
<div><br class="">
<blockquote type="cite" class="">
<div class="">On 21 Dec 2022, at 22:22, Rob Bygrave <<a href="mailto:robin.bygrave@gmail.com" class="">robin.bygrave@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">
<div dir="ltr" class="">
<div class="">A "solution / fix" to this issue that modifies the internals of <i class="">
java.util.concurrent.ThreadPerTaskExector</i> is to:</div>
<div class=""><b class=""><br class="">
</b></div>
<div class=""><b class=""><br class="">
</b></div>
<div class=""><b class="">1) Add a new interface InterruptableTask</b></div>
<div class=""><br class="">
</div>
<div class=""><span style="font-family:monospace" class="">public interface InterruptableTask {<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class=""><br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">    /**</span></div>
<div class=""><span style="font-family:monospace" class="">     * Return true if this is a task that is deemed to be in an idle state that can be interrupted.<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">     */<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">    boolean canInterrupt();<br class="">
}</span></div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><b class="">2) Modify java.util.concurrent.ThreadPerTaskExector by:</b></div>
<div class=""><br class="">
</div>
<div class=""><b class="">2i)</b> Changing the threads field from storing just Thread to additionally storing the associated task (Runnable or Callable)
<br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><span style="font-family:monospace" class="">// instead of ...<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">private final Set<Thread> threads = ConcurrentHashMap.newKeySet();<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class=""><br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">// use a Map with values being the tasks (Runnable or Callable)<br class="">
</span></div>
<div class=""><span style="font-family:monospace" class="">private final Map<Thread, Object> threadTasks = new ConcurrentHashMap<>();</span></div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><b class="">2ii)</b> Add a new internal method tryStopInterruptableTask():</div>
<div class=""><br class="">
</div>
<div class=""><span style="font-family:monospace" class="">private void tryStopInterruptableTask() {<br class="">
  threadTasks.entrySet().stream()<br class="">
       .filter(entry -> entry.getKey().isAlive()) // Thread isAlive<br class="">
       .filter(entry -> entry.getKey().getState() == Thread.State.WAITING) // Thread WAITING state<br class="">
       .forEach(entry -> {<br class="">
         if (entry.getValue() instanceof InterruptableTask task) {<br class="">
           if (task.canInterrupt()) { // application deems this task to NOT be in-flight (e.g. not IO waiting on database response)<br class="">
             entry.getKey().interrupt();<br class="">
           }<br class="">
         }<br class="">
       });<br class="">
}</span></div>
<div class=""><br class="">
</div>
<div class=""><b class="">2 iii)</b> Call this method as part of shutdown() (or perhaps the internal tryShutdownAndTerminate())</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">With these changes, then the Nima specific ConnectionHandler just needs to implement InterruptableTask and then the usual
<br class="">
</div>
<div class="">shutdown of the ExecutorService operates nicely.</div>
<div class=""><br class="">
</div>
<div class=""><span style="font-family:monospace" class="">executor.shutdown();<br class="">
if (!executor.awaitTermination(gracefulShutdownMillis, TimeUnit.MILLISECONDS)) {<br class="">
    List<Runnable> running = executor.shutdownNow();<br class="">
    if (!running.isEmpty()) {<br class="">
        LOGGER.log(INFO, running.size() + " channel tasks did not terminate gracefully");<br class="">
    }<br class="">
}</span></div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class=""><br class="">
</div>
<div class="">Cheers, Rob.<br class="">
</div>
</div>
<br class="">
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</body>
</html>