
Use QR code for Q&A

java.lang.Thread: platform (OS) and virtual
public class Framework {
private static final ScopedValue<Request> REQUEST = ScopedValue.newInstance();
private LinkedHashMap<String, Callable<Response>> actions = new LinkedHashMap<>();
...
public Response execute(Request request, Callable<Response> action) { // In some thread...
var action = actions.get(request.getServletPath()); // Ignoring path matching...
return ScopedValue.where(REQUEST, request).call(action); // Bind value
// Value unbound here
}
} ...
actions.put(path, () -> {
var request = Framework.REQUEST.get();
...
});
goto
goto with branches, loops, functions
try (var scope = StructuredTaskScope.open()) {
Supplier<T1> subtask1 = scope.fork(callable1); // runs on virtual thread
Supplier<T2> subtask2 = scope.fork(callable2); // runs on another virtual thread
scope.join(); // blocks until completion
// Process subtask1.get(), subtask2.get()
}
join failsopen
client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenApply(this::getImageURLs) .thenCompose(this::getImages) .thenAccept(this::saveImages) .exceptionally(this::ohNoes);
try {
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
for (URL url : getImageURLs(response.body())) {
saveImage(getImage(url));
}
}
catch (...) { ... }

spring.threads.virtual.enabled=true
@Path("/sleep")
public class Sleep {
@Path("/virtual")
@RunOnVirtualThread
@GET
@Produces(MediaType.TEXT_PLAIN)
public String virtual() {
try {
Thread.sleep(1_000);
} catch (InterruptedException __) {
}
return Thread.currentThread() + "\r\n";
}
}
/platform and /virtual
cd ~/projects/2025-jcon mvn install -Dmaven.test.skip=true java --enable-preview -jar target/quarkus-app/quarkus-run.jar
curl localhost:8080/sleep/platform curl localhost:8080/sleep/virtual


bombardier --requests=1000 --connections=1000 --timeout=60s --print=i,p,r http://localhost:8080/sleep/platform bombardier --requests=1000 --connections=1000 --timeout=60s --print=i,p,r http://localhost:8080/sleep/virtual
curl localhost:8080/search/platform/record bombardier --requests=100 --connections=100 --timeout=60s --print=i,p,r http://localhost:8080/search/platform/record bombardier --requests=100 --connections=100 --timeout=60s --print=i,p,r http://localhost:8080/search/virtual/record

jcmd to get PID of server processjcmd pid JFR.start bombardier ... jcmd pid JFR.dump name=1 filename=dumpfile
jfr configure jdk.VirtualThreadStart#enabled=true jdk.VirtualThreadEnd#enabled=true --output custom.jfc jcmd pid JFR.start setting=custom.jfc

java --enable-preview -jar target/quarkus-app/quarkus-run.jar bombardier --requests=10000 --connections=10000 --timeout=60s --print=i,p,r http://localhost:8080/sleep/virtual jcmd jcmd pid VM.native_memory
Thread- Thread (reserved=64705KB, committed=5353KB)
(threads #63)
- Thread (reserved=191070KB, committed=19070KB)
(threads #186)
-Xss
curl localhost:8080/image/1 | display
bombardier --timeout=60s --connections=500 --requests=500 --print=i,p,r localhost:8080/image/1
HTTP codes:
1xx - 0, 2xx - 388, 3xx - 0, 4xx - 0, 5xx - 112
private static Semaphore sem = new Semaphore(20);
...
sem.acquire();
try {
byte[] image = randomImage();
return ...;
} finally {
sem.release();
}
bombardier --timeout=60s --connections=500 --requests=500 --print=i,p,r localhost:8080/image/2

synchronized)ConcurrentHashMap)java -Djdk.tracePinnedThreads=full --enable-preview -jar target/quarkus-app/quarkus-run.jar
curl localhost:8080/sleep/pin
-Djdk.tracePinnedThreads in production; look for VirtualThreadPinned events in JFRbombardier --timeout=60s --connections=100 --requests=100 --print=i,p,r localhost:8080/sleep/pinView threads in
jconsole
-Djdk.virtualThreadScheduler.maxPoolSizebombardier --timeout=60s --connections=200 --requests=200 --print=i,p,r localhost:8080/search/concurrent/record jconsoleAre there more ForkJoinPool-1-worker-n threads than cores?

bombardier --timeout=60s --connections=10000 --requests=10000 --print=i,p,r http://localhost:8080/sleep/reactive
ExecutorService.invokeAll/invokeAny
SimpleDateFormatter, ObjectMapper)-Djdk.traceVirtualThreadLocals=true to see when virtual thread sets thread localpublic class Thread {
...
ThreadLocal.ThreadLocalMap threadLocals;
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
}
java --enable-preview --add-opens=java.base/java.lang=ALL-UNNAMED -jar target/quarkus-app/quarkus-run.jar curl http://localhost:8080/threadlocal/platform curl http://localhost:8080/threadlocal/virtual curl http://localhost:8080/threadlocal/platform/verbose curl http://localhost:8080/threadlocal/virtual/verbose

jconsole and watch memory
curl http://localhost:8080/threadlocal/virtual/props bombardier --timeout=60s --connections=100 --requests=10000 --print=i,p,r http://localhost:8080/threadlocals/platform/props bombardier --timeout=60s --connections=100 --requests=10000 --print=i,p,r http://localhost:8080/threadlocals/virtual/props bombardier --timeout=60s --connections=100 --requests=10000 --print=i,p,r http://localhost:8080/threadlocals/scoped/props

synchronized, native methods, foreign functions)