Reputation: 643
On Windows 11, Java 22, preview enabled, I am trying to use (JEP 453)'s joinUntil functionality to limit execution duration.
However, I am not able to use it in a nested way. The execution is not stopping even though I used scope.joinUntil.
Could you help me figure it out what is wrong with the code? I don't want to use it only in my main function, but also in my sub projects.
Project code: github
public class Main {
public static void main(String... s) {
nestedTest_pureJava(
Duration.ofSeconds(8),
Duration.ofSeconds(5),
5
);
}
private static void nestedTest_pureJava(Duration untilTimeout, Duration workLoad, int nestedId) {
if (nestedId < 0) {
out.println("nestedTest_pureJava -> skip -> " + nestedId);
return;
}
out.println("nestedTest_pureJava -> begin -> " + nestedId);
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
scope.fork(() -> {
Thread.sleep(workLoad);
return null;
});
scope.joinUntil(Instant.now().plusSeconds(untilTimeout.getSeconds()));
scope.throwIfFailed();
nestedTest_pureJava(untilTimeout, workLoad, nestedId - 1);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
throw new RuntimeException(e);
}
out.println("nestedTest_pureJava -> end -> " + nestedId);
}
}
Output:
nestedTest_pureJava -> begin -> 5
nestedTest_pureJava -> begin -> 4
nestedTest_pureJava -> begin -> 3
nestedTest_pureJava -> begin -> 2
nestedTest_pureJava -> begin -> 1
nestedTest_pureJava -> begin -> 0
nestedTest_pureJava -> skip -> -1
nestedTest_pureJava -> end -> 0
nestedTest_pureJava -> end -> 1
nestedTest_pureJava -> end -> 2
nestedTest_pureJava -> end -> 3
nestedTest_pureJava -> end -> 4
nestedTest_pureJava -> end -> 5
As I am catching the TimeoutException, I have tried to shutdown the scope, but the problem still persists.
private static void nestedTest_pureJava(Duration untilTimeout, Duration workLoad, int nestedId) {
if (nestedId < 0) {
out.println("nestedTest_pureJava -> skip -> " + nestedId);
return;
}
out.println("nestedTest_pureJava -> begin -> " + nestedId);
var scope = new StructuredTaskScope.ShutdownOnFailure();
try {
scope.fork(() -> {
Thread.sleep(workLoad);
return null;
});
scope.joinUntil(Instant.now().plusSeconds(untilTimeout.getSeconds()));
scope.throwIfFailed();
nestedTest_pureJava(untilTimeout, workLoad, nestedId - 1);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
if (e instanceof TimeoutException) {
scope.shutdown();
}
throw new RuntimeException(e);
} finally {
scope.close();
}
out.println("nestedTest_pureJava -> end -> " + nestedId);
}
Upvotes: 1
Views: 134
Reputation: 643
As Holger already answered the recursive-code should be inside 'scope.fork(...)'
public class Main {
public static void main(String... s) {
nestedTest_pureJava(
Duration.ofSeconds(8),
Duration.ofSeconds(5),
5
);
}
private static void nestedTest_pureJava(Duration untilTimeout, Duration workLoad, int nestedId) {
if (nestedId < 0) {
out.println("nestedTest_pureJava -> skip -> " + nestedId);
return;
}
out.println("nestedTest_pureJava -> begin -> " + nestedId);
var scope = new StructuredTaskScope.ShutdownOnFailure();
try {
scope.fork(() -> {
Thread.sleep(workLoad);
nestedTest_pureJava(untilTimeout, workLoad, nestedId - 1);
return null;
});
scope.joinUntil(Instant.now().plusSeconds(untilTimeout.getSeconds()));
scope.throwIfFailed();
} catch (InterruptedException | TimeoutException | ExecutionException e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
if (e instanceof TimeoutException) {
scope.shutdown();
}
throw new RuntimeException(e);
} finally {
scope.close();
}
out.println("nestedTest_pureJava -> end -> " + nestedId);
}
}
Upvotes: 1