Hi Josiah,
On 13/05/2025 20:24, Josiah Noel wrote:
The HttpServer doesn't use any default
executor
I know what you mean by this, but I have to point out that the class
used is quite literally called DefaultExecutor
<https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/e7ce661adb01fba4bb690d51cc2858c822008654/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java*L200-L204__;Iw!!ACWV5N9M2RV99hQ!JIfxp_rcxH9VkMOYILi4aLebtIM5Y9gOIT0jc3AgmPwkxmgz5lo2R7v9Q71TuUH5pHVtxuVS0pg5RjTkITf00A$>.>
For backward compatibility I don't think we will ever
change that default behaviour.
Oh - right - I see what you meant too then.
Can you expand on this a little more? Is the backwards incompatibility
that it would be able to serve more than a single request at the same time?
Yes. An application (handler's implementations) may depend on that.
An executor can however be supplied to the HttpServer
using `HttpServer.setExecutor` [1]
After using this method for so long, I'm wondering if there is any
reason that we have to go through this ceremony to serve more than one
request at the same time. (Every time I've used it)
Probably to give control to the application over what kind
of executor it wants to use. There are many parameters there,
like should the threads be daemon? What should be the
Thread Context ClassLoader? What should be the thread names?
Should it be a pool executor, if so what should be the size
of the pool? No default choice would suit everybody.
Using a VirtualThreadPerTaskExecutor would eliminate most of
these questions, but virtual threads were not there when
the API was designed. IMO having a single thread was not an
unreasonable default, when there was an API to override
that and let the application provide the executor of its choice.
Their might still be some side effect with using
virtual thread however, especially if invoking code
calling a native method that blocks, or loading a class
that blocks in its static initializers.
As you say, the default dispatcher currently runs serially, so if one
does any sort of blocking operation, the dispatcher thread is pinned and
cannot serve any more requests. If one were to switch to a virtual
thread executor and call native blocking methods, is there a difference
in this scenario? Either way, the server would be unable to serve
requests while the thread is pinned by the blocking operation.
Blocking does not mean deadlocking, but if virtual threads get
pinned it can lead to carrier thread starvation: the code that
would "unblock" everything might never get executed because all
carrier threads are pinned.
best regards,
-- daniel