<div dir="ltr"><p>I hope this message finds you well. Thank you for all the work you are doing to improve the Java platform.</p>
<p>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 <code>StructuredTaskScope</code> together with <code>ArrayBlockingQueue</code> as a “channel.” The intention is to build groups of task pipelines step by step that can be executed in parallel.</p>
<p>Here’s a simplified snippet that captures the idea:</p><div><br></div><div>void main(){<br>    var producerChannel = new ArrayBlockingQueue<HttpRequest>(100);<br>    var consumerChannel = new ArrayBlockingQueue<HttpResponse<String>>(3);<br>    var client = HttpClient.newBuilder().build();<br>    var request = HttpRequest.newBuilder()<br>        .uri(URI.create("some url"))<br>        .build();<br>    try(var routine = StructuredTaskScope.open()){<br>        for(var i = 0; i < 100; i++){<br>            routine.fork(() -> sendRequest(producerChannel, consumerChannel, client));<br>            producerChannel.put(request);<br>        }<br><br>        routine.fork(() -> processResponse(consumerChannel));<br>        routine.join();<br><br>    } catch (InterruptedException e) {<br>        throw new RuntimeException(e);<br>    }<br><br>}<br><br>Void sendRequest(ArrayBlockingQueue<HttpRequest> producerChannel,<br>                          ArrayBlockingQueue<HttpResponse<String>> consumerChannel,<br>                          HttpClient client) throws InterruptedException, IOException {<br>    var req = producerChannel.take();<br>    var res = client.send(req, HttpResponse.BodyHandlers.ofString());<br>    consumerChannel.put(res);<br>    return null;<br>}<br><br>Void processResponse(ArrayBlockingQueue<HttpResponse<String>> consumerChannel) throws InterruptedException {<br>    for (var i = 0; i < 100; i++){<br>        var value = consumerChannel.take().body();<br>        println(value);<br>    }<br>    var value = consumerChannel.take().body();<br>    println(value);<br>    return null;<br>}</div><div><br></div><div><p>One thing I noticed is that having to declare <code>Void</code> and return <code>null</code> introduces a bit of noise. This ceremony is required because <code>Runnable</code> 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.</p>
<p>This makes the <code>Void</code> return type and <code>return null</code> feel redundant. I was wondering: would it be worth considering the addition of a <code>Runnable</code>-like functional interface that permits checked exceptions?</p>
<p>Thank you for your time and consideration. I’d love to hear your thoughts.</p>
<p>Best regards and always yours.</p><p>David Grajales Cárdenas.</p></div></div>