javaadvanced
Virtual Threads — Lightweight Concurrency
Use Java 21 virtual threads for massive concurrency without thread pool tuning or reactive frameworks.
javaPress ⌘/Ctrl + Shift + C to copy
import java.net.URI;
import java.net.http.*;
import java.time.*;
import java.util.concurrent.*;
import java.util.stream.*;
import java.util.List;
public class VirtualThreadDemo {
// 1. Start a virtual thread
public static void basic() throws InterruptedException {
Thread vt = Thread.ofVirtual().name("worker").start(() -> {
System.out.println(Thread.currentThread());
});
vt.join();
}
// 2. ExecutorService with virtual threads
public static void withExecutor() throws Exception {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
// Submit 10,000 concurrent tasks — no pool sizing needed
List<Future<String>> futures = IntStream.range(0, 10_000)
.mapToObj(i -> executor.submit(() -> fetchData(i)))
.toList();
for (var future : futures) {
System.out.println(future.get());
}
}
}
// 3. Structured concurrency (preview)
public static void structured() throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Subtask<String> user = scope.fork(() -> fetchData(1));
Subtask<String> orders = scope.fork(() -> fetchData(2));
scope.join().throwIfFailed();
System.out.println(user.get() + " | " + orders.get());
}
}
// 4. HTTP calls — 1000 concurrent with virtual threads
public static void httpParallel() throws Exception {
HttpClient client = HttpClient.newHttpClient();
Instant start = Instant.now();
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
List<Future<Integer>> results = IntStream.range(0, 1000)
.mapToObj(i -> executor.submit(() -> {
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/get"))
.build();
return client.send(req, HttpResponse.BodyHandlers.ofString()).statusCode();
}))
.toList();
long success = results.stream()
.map(f -> { try { return f.get(); } catch (Exception e) { return 0; } })
.filter(code -> code == 200)
.count();
System.out.printf("%d OK in %s%n", success, Duration.between(start, Instant.now()));
}
}
static String fetchData(int id) {
try { Thread.sleep(Duration.ofMillis(50)); } catch (InterruptedException e) {}
return "Data-" + id;
}
public static void main(String[] args) throws Exception {
basic();
withExecutor();
}
}Use Cases
- High-concurrency web servers handling thousands of requests
- Parallel API calls without reactive complexity
- Replacing thread pools with lightweight virtual threads
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
javaadvanced
Virtual Threads — Practical Patterns
Use Java 21 virtual threads for high-concurrency I/O: per-request threads, structured scopes, and limits.
Best for: High-concurrency I/O-bound servers
#java#virtual-threads
javaintermediate
CompletableFuture — Async Programming
Chain async operations with CompletableFuture: thenApply, thenCompose, allOf, and exception handling.
Best for: Parallel API calls to multiple services
#java#async
javaintermediate
ExecutorService — Thread Pool Management
Create and manage thread pools with ExecutorService: fixed, cached, scheduled, and custom pools.
Best for: Managing concurrent task execution
#java#concurrency
javaadvanced
Concurrent Collections — Thread-Safe Maps
Use ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue for thread-safe data structures.
Best for: Thread-safe caching in multi-threaded applications
#java#concurrency