Feedback about structured Concurrency and proposing of a new functional interface akin runnable
David Alayachew
davidalayachew at gmail.com
Thu Sep 4 03:20:44 UTC 2025
Full agreement on the suggestion to have the Runnable-like interface that
throws. It's common enough that it would be very useful for me. Void was a
workaround for a bad situation, but it doesn't mean we should have to be
stuck with it for a new API.
On Wed, Sep 3, 2025 at 11:16 PM david Grajales <david.1993grajales at gmail.com>
wrote:
> I hope this message finds you well. Thank you for all the work you are
> doing to improve the Java platform.
>
> I wanted to share some thoughts from a small experiment I’ve been running
> with structured concurrency. The idea was to mimic (to some extent) Go’s
> goroutines and channels, modeling an N:M producer–consumer fan-out using
> StructuredTaskScope together with ArrayBlockingQueue as a “channel.” The
> intention is to build groups of task pipelines step by step that can be
> executed in parallel.
>
> Here’s a simplified snippet that captures the idea:
>
> void main(){
> var producerChannel = new ArrayBlockingQueue<HttpRequest>(100);
> var consumerChannel = new ArrayBlockingQueue<HttpResponse<String>>(3);
> var client = HttpClient.newBuilder().build();
> var request = HttpRequest.newBuilder()
> .uri(URI.create("some url"))
> .build();
> try(var routine = StructuredTaskScope.open()){
> for(var i = 0; i < 100; i++){
> routine.fork(() -> sendRequest(producerChannel,
> consumerChannel, client));
> producerChannel.put(request);
> }
>
> routine.fork(() -> processResponse(consumerChannel));
> routine.join();
>
> } catch (InterruptedException e) {
> throw new RuntimeException(e);
> }
>
> }
>
> Void sendRequest(ArrayBlockingQueue<HttpRequest> producerChannel,
> ArrayBlockingQueue<HttpResponse<String>>
> consumerChannel,
> HttpClient client) throws InterruptedException,
> IOException {
> var req = producerChannel.take();
> var res = client.send(req, HttpResponse.BodyHandlers.ofString());
> consumerChannel.put(res);
> return null;
> }
>
> Void processResponse(ArrayBlockingQueue<HttpResponse<String>>
> consumerChannel) throws InterruptedException {
> for (var i = 0; i < 100; i++){
> var value = consumerChannel.take().body();
> println(value);
> }
> var value = consumerChannel.take().body();
> println(value);
> return null;
> }
>
> One thing I noticed is that having to declare Void and return null
> introduces a bit of noise. This ceremony is required because Runnable
> doesn’t allow checked exceptions in its contract (and never will, for
> backwards compatibility). Yet, in practice, many real-world tasks don’t
> return values directly — instead, they write to or consume from buffers.
>
> This makes the Void return type and return null feel redundant. I was
> wondering: would it be worth considering the addition of a Runnable-like
> functional interface that permits checked exceptions?
>
> Thank you for your time and consideration. I’d love to hear your thoughts.
>
> Best regards and always yours.
>
> David Grajales Cárdenas.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250903/2c6b804a/attachment.htm>
More information about the loom-dev
mailing list