JEP 480: Structured Concurrency (Third Preview) Feedback
Winkelman, Kyle G
kyle.winkelman at optum.com
Tue Oct 15 17:13:42 UTC 2024
Things that felt strange or annoying:
* When subclassing StructuredTaskScope I always have to @Override `join` and `joinUntil` to return my subclass type to provide a fluent api.
* When subclassing StructuredTaskScope @Override `handleComplete` I find myself wanting to write a switch expression on Subtask#state(), but if I do, I always need to have a case for UNAVAILABLE and throw IllegalStateException.
* Using StructuredTaskScope (no subclassing) feels weird because you must decide to use either the `<>` diamond operator to allow any types or define a type T for restricting subtasks (makes you wonder if you are using it correctly). Whereas, both ShutdownOnFailure and ShutdownOnSuccess just feel right to use.
* In IntelliJ the Javadoc of StructuredTaskScope doesn’t seem to properly format and makes it very difficult to read (probably an issue with IntelliJ).
* Blocking IO is not interruptible and this can cause confusion when the scope won’t close in a timely manner even though something may have already thrown an exception (probably falls under the Non-Goal of thread cancellation mechanism). e.g. 2 calls to fork one reading a short file and the other reading an long file, short one fails, if I don’t do something to close the long file stream I will read the whole thing (making ShutdownOnFailure not really live up to its name).
I love that StructuredTaskScope interrupts threads on close/shutdown (it allows some short-circuiting that I struggled with when using Executors.newVirtualThreadPerTaskExecutor()). Here is my new favorite code snippet using StructuredTaskScope:
#!java --source 23 --enable-preview
import java.io.*;
import java.util.concurrent.*;
import java.util.function.Supplier;
void main() throws ExecutionException, InterruptedException, IOException {
System.out.println(process("Hello, World!", "cat"));
}
ProcessResult process(String input, String... command)
throws ExecutionException, InterruptedException, IOException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var process = new ProcessBuilder(command).start();
scope.fork(write(process::getOutputStream, input));
var stdout = scope.fork(read(process::getInputStream));
var stderr = scope.fork(read(process::getErrorStream));
var exitValue = scope.fork(waitForOrDestroy(process));
scope.join().throwIfFailed();
return new ProcessResult(stdout.get(), stderr.get(), exitValue.get());
}
}
Callable<Void> write(Supplier<OutputStream> outputStreamSupplier, String input) {
return () -> {
try (var outputStream = outputStreamSupplier.get()) {
outputStream.write(input.getBytes());
return null;
}
};
}
Callable<String> read(Supplier<InputStream> inputStreamSupplier) {
return () -> {
try (var inputStream = inputStreamSupplier.get()) {
return new String(inputStream.readAllBytes());
}
};
}
Callable<Integer> waitForOrDestroy(Process process) {
return () -> {
try {
return process.waitFor();
} catch (InterruptedException e) {
process.destroy();
throw e;
}
};
}
record ProcessResult(String stdout, String stderr, int exitValue) {}
This e-mail, including attachments, may include confidential and/or
proprietary information, and may be used only by the person or entity
to which it is addressed. If the reader of this e-mail is not the intended
recipient or intended recipient’s authorized agent, the reader is hereby
notified that any dissemination, distribution or copying of this e-mail is
prohibited. If you have received this e-mail in error, please notify the
sender by replying to this message and delete this e-mail immediately.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20241015/ebbae78d/attachment-0001.htm>
More information about the loom-dev
mailing list