I am trying to use StructuredTaskScope on Java 25. However, I could not to trigger StructuredTaskScope.TimeoutException.
Please find the code here and below:
package com.tugalsan.tst.thread;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Joiner;
import java.util.concurrent.StructuredTaskScope.Subtask.State;
public class Main {
public static void main(String... s) {
Callable<String> tenSecsTask = () -> {
Thread.sleep(Duration.ofSeconds(10));
return "a";
};
var allAwait = allAwait("allAwait", Duration.ofSeconds(2), tenSecsTask);
allAwait.resultsSuccessful().forEach(IO::println);
IO.println("main.done..");
}
public static record AllAwait<R>(String name, Duration timeout, List<R> resultsSuccessful, List<StructuredTaskScope.Subtask<R>> resultsFailedOrUnavailable, Optional<StructuredTaskScope.TimeoutException> timeoutException) {
}
public static <R> AllAwait<R> allAwait(String name, Duration timeout, Callable<R>... callables) {
try (var scope = StructuredTaskScope.open(Joiner.<R>awaitAll(),
cf -> {
if (name != null) {
cf.withName(name);
}
if (timeout != null) {
cf.withTimeout(timeout);
}
return cf;
}
)) {
var subTasks = Arrays.stream(callables).map(scope::fork).toList();
scope.join();
var resultsSuccessful = subTasks.stream().filter(st -> st.state() == State.SUCCESS).map(StructuredTaskScope.Subtask::get).toList();
var resultsFailedOrUnavailable = subTasks.stream().filter(st -> st.state() == State.FAILED || st.state() == State.UNAVAILABLE).toList();
return new AllAwait(name, timeout, resultsSuccessful, resultsFailedOrUnavailable, Optional.empty());
} catch (InterruptedException | StructuredTaskScope.TimeoutException e) {
throwIfInterruptedException(e);
if (e instanceof StructuredTaskScope.TimeoutException et) {
return new AllAwait(name, timeout, List.of(), List.of(), Optional.of(et));
}
return null;
}
}
....
}
Console output shows, the callable finishes its work successfully, but it is supposed to fail.
Executing command line: [C:\bin\java\home\bin\java.exe, --enable-preview, --enable-preview, --add-modules, jdk.incubator.vector, -classpath, C:\git\tst\com.tugalsan.tst.thread\target\classes, com.tugalsan.tst.thread.Main]
WARNING: Using incubator modules: jdk.incubator.vector
a
main.done..
I have missed adding the InterruptedException handling code before. Please find it below as well:
@SuppressWarnings("unchecked")
private static <T extends Throwable> void _throwAsUncheckedException(Throwable exception) throws T {
throw (T) exception;
}
@Deprecated //only internalUse
private static void throwAsUncheckedException(Throwable exception) {
Main.<RuntimeException>_throwAsUncheckedException(exception);
}
public static <R> R throwIfInterruptedException(Throwable t) {
if (isInterruptedException(t)) {
Thread.currentThread().interrupt();
throwAsUncheckedException(t);
}
return null;
}
public static boolean isInterruptedException(Throwable t) {
if (t instanceof InterruptedException) {
return true;
}
if (t.getCause() != null) {
return isInterruptedException(t.getCause());
}
return false;
}
You are not creating the StructuredTaskScope with a timeout as required for a StructuredTaskScope.Timeout exception to be thrown.
Why? Because the documentation for StructuredTaskScope.Configuration#withTimeout() says:
Returns a new { Configuration} object with the given timeout. The other components are the same as this object.
But you throw away that new Configuration object and return the unconfigured Configuration object.
You should create your StructuredTaskScope as
try (var scope = StructuredTaskScope.open(Joiner.<R>awaitAll(),
cf -> cf.withName(name).withTimeout(timeout);
)) {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With