Java Concurrency from the Trenches: Navigating IO-Bound Challenges at Scale
These articles are AI-generated summaries. Please check the original sources for full details.
Transcript
Hugo Marques discusses lessons learned optimizing Java concurrency for a high-throughput IO-bound job at Netflix, moving from naive parallelization to a refined solution utilizing virtual threads and careful resource management. The initial job processed 10 regions, each with 10K orders and 5K products, requiring approximately 270K requests per second to a downstream gRPC service.
Early attempts at parallelization with nested parallel streams and CompletableFutures, while seemingly straightforward, led to out-of-memory errors and potential downstream service overload, despite appearing correct in initial testing. The core issue was a lack of control over concurrency, resulting in unbounded task accumulation and resource exhaustion.
Key Insights
- Nested Parallel Streams Pitfall, 2024: Applying parallel streams within flatMap transformations can result in sequential execution due to OpenJDK implementation details.
- Backpressure is Crucial: Uncontrolled concurrency can overwhelm downstream services, leading to denial-of-service-like behavior; rate limiting and semaphores are essential for managing load.
- Virtual Threads Simplify Concurrency: Java’s virtual threads offer a lightweight concurrency model, reducing the need for complex thread pool management, but still require careful consideration to avoid unbounded task creation.
Working Example
// Example of using a Semaphore to limit concurrent tasks
Semaphore semaphore = new Semaphore(50); // Limit to 50 concurrent tasks
CompletableFuture<Void> processOrder(Order order) {
return CompletableFuture.supplyAsync(() -> {
try {
semaphore.acquire(); // Acquire a permit
// Process the order and make gRPC calls
return processOrderDetails(order);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} finally {
semaphore.release(); // Release the permit
}
});
}
Practical Applications
- Netflix Job Processing: Optimized a critical batch job to process a large volume of orders and products efficiently, ensuring timely completion and preventing downstream service overload.
- Pitfall: Over-reliance on CompletableFutures without proper backpressure mechanisms can lead to uncontrolled concurrency and resource exhaustion, resulting in out-of-memory errors or service degradation.
References:
Continue reading
Next article
Researchers Uncover Service Providers Fueling Industrial-Scale Pig Butchering Fraud
Related Content
JEP 525 Refines Structured Concurrency with Timeout Handling in Java 26
JEP 525, included in JDK 26, introduces a timeout callback for custom joiners in structured concurrency, improving error handling and flexibility.
Deep Dive into Fastjson Deserialization Vulnerabilities: From Principles to Practical Defense
This article details Fastjson deserialization vulnerabilities, particularly CVE-2022-25845, which can lead to Remote Code Execution (RCE).
Java Ecosystem Update: Jakarta EE 12, Liberica JDK Patches, and More
This Java roundup from November 17th, 2025 highlights the progress toward Jakarta EE 12 completion and security patches for Liberica JDK.