<div dir="ltr"><div><i>> separate the “idle” and “busy” threads by spawning them in different ExecutorServices</i></div><div><br></div><div>That makes perfect sense, thanks!!  I'll look to work this through.</div><div><br></div>Cheers, Rob.<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 23 Dec 2022 at 03:29, Ron Pressler <<a href="mailto:ron.pressler@oracle.com">ron.pressler@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">



<div style="overflow-wrap: break-word;">
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><br>
</div>
<div>— Ron<br>
<div><br>
<blockquote type="cite">
<div>On 21 Dec 2022, at 22:22, Rob Bygrave <<a href="mailto:robin.bygrave@gmail.com" target="_blank">robin.bygrave@gmail.com</a>> wrote:</div>
<br>
<div>
<div dir="ltr">
<div dir="ltr">
<div>A "solution / fix" to this issue that modifies the internals of <i>
java.util.concurrent.ThreadPerTaskExector</i> is to:</div>
<div><b><br>
</b></div>
<div><b><br>
</b></div>
<div><b>1) Add a new interface InterruptableTask</b></div>
<div><br>
</div>
<div><span style="font-family:monospace">public interface InterruptableTask {<br>
</span></div>
<div><span style="font-family:monospace"><br>
</span></div>
<div><span style="font-family:monospace">    /**</span></div>
<div><span style="font-family:monospace">     * Return true if this is a task that is deemed to be in an idle state that can be interrupted.<br>
</span></div>
<div><span style="font-family:monospace">     */<br>
</span></div>
<div><span style="font-family:monospace">    boolean canInterrupt();<br>
}</span></div>
<div><br>
</div>
<div><br>
</div>
<div><b>2) Modify java.util.concurrent.ThreadPerTaskExector by:</b></div>
<div><br>
</div>
<div><b>2i)</b> Changing the threads field from storing just Thread to additionally storing the associated task (Runnable or Callable)
<br>
</div>
<div><br>
</div>
<div><span style="font-family:monospace">// instead of ...<br>
</span></div>
<div><span style="font-family:monospace">private final Set<Thread> threads = ConcurrentHashMap.newKeySet();<br>
</span></div>
<div><span style="font-family:monospace"><br>
</span></div>
<div><span style="font-family:monospace">// use a Map with values being the tasks (Runnable or Callable)<br>
</span></div>
<div><span style="font-family:monospace">private final Map<Thread, Object> threadTasks = new ConcurrentHashMap<>();</span></div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div><b>2ii)</b> Add a new internal method tryStopInterruptableTask():</div>
<div><br>
</div>
<div><span style="font-family:monospace">private void tryStopInterruptableTask() {<br>
  threadTasks.entrySet().stream()<br>
       .filter(entry -> entry.getKey().isAlive()) // Thread isAlive<br>
       .filter(entry -> entry.getKey().getState() == Thread.State.WAITING) // Thread WAITING state<br>
       .forEach(entry -> {<br>
         if (entry.getValue() instanceof InterruptableTask task) {<br>
           if (task.canInterrupt()) { // application deems this task to NOT be in-flight (e.g. not IO waiting on database response)<br>
             entry.getKey().interrupt();<br>
           }<br>
         }<br>
       });<br>
}</span></div>
<div><br>
</div>
<div><b>2 iii)</b> Call this method as part of shutdown() (or perhaps the internal tryShutdownAndTerminate())</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>With these changes, then the Nima specific ConnectionHandler just needs to implement InterruptableTask and then the usual
<br>
</div>
<div>shutdown of the ExecutorService operates nicely.</div>
<div><br>
</div>
<div><span style="font-family:monospace">executor.shutdown();<br>
if (!executor.awaitTermination(gracefulShutdownMillis, TimeUnit.MILLISECONDS)) {<br>
    List<Runnable> running = executor.shutdownNow();<br>
    if (!running.isEmpty()) {<br>
        LOGGER.log(INFO, running.size() + " channel tasks did not terminate gracefully");<br>
    }<br>
}</span></div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>Cheers, Rob.<br>
</div>
</div>
<br>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>

</blockquote></div>