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