Pages

Thursday, April 23, 2026

Java Platform Threads Limit: Performance Impact & Cost Guide

Wondering what makes Java applications hard to scale up to thousands of concurrent tasks?

The solution is the cost of platform threads, which are the traditional Java threads. In this blog, we will discuss the behavior of platform threads when loaded, limitations, and why developers are moving to the new virtual threads of Java in order to scale.

Thread related topics

Java Platform Threads are Costly

Java platform threads are costly because of:

  • OS-level memory
  • Context switching
  • Lifecycle costs

Java platform threads are heavyweight operating system threads, which:

  • Use a lot of memory (usually 1MB stack memory)
  • Are costly to create and operate at large scale

The JVM throws errors like:

OutOfMemoryError: unable to create new native thread

What are Platform Threads in Java?

Java has a traditional thread supported by a native operating system thread called a platform thread.

Each thread:

  • Is created with new Thread API
  • Takes dedicated stack memory (1MB by default)
  • Is restricted by OS thread limits

Java Thread Class Explained

Important Features of Platform Threads

Feature

Platform Thread

Backed By

OS native thread (e.g., POSIX thread)

Stack Memory

Between 1MB and 10MB (-Xss)

Creation Cost

High

Scalability

Limited

Blocking Operations

Blocks the OS thread

Why Thread Creation Cost Matters

Java apps in microservice architecture frequently perform I/O-bound operations.

These operations:

  • Block threads
  • Keep them idle until response

To handle high concurrency, developers try to:

Increase number of threads

But platform threads are expensive because:

  • Large memory consumption per thread
  • OS-imposed limits
  • Performance bottlenecks under load


Let’s explore this with a practical example.


Java Thread Creation Demo – Hands-On


We'll simulate a typical I/O-heavy workload using Thread.sleep() to mimic latency, and then create thousands of threads to see what happens.

Project Setup

  • Java Version: 21 (for Duration.ofSeconds)
  • Tools: IntelliJ IDEA or any Java IDE


Simulate I/O With Thread.sleep()


 public class Task {
     private static final Logger logger = LogManager.getLogger(Task.class);

     public static void ioIntensive(int i) {
         logger.info("Starting IO Task: " + i + " - " + Thread.currentThread().getName());
         try {
             Thread.sleep(Duration.ofSeconds(10));
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
         }
         logger.info("Ending IO Task: " + i + " - " + Thread.currentThread().getName());
     }
 }
 

Why Thread.sleep()?

It simulates thread blocking behavior, similar to network calls, without external dependencies.

Creating Threads in a Loop


 public class InboundOutboundTaskDemo {
     private static final int MAX_PLATFORM_THREADS = 50_000;

     public static void main(String[] args) {
         for (int i = 0; i < MAX_PLATFORM_THREADS; i++) {
             final int taskNumber = i;
             Thread thread = new Thread(() -> Task.ioIntensive(taskNumber));
             thread.start();
         }
     }
 }
 

Execution Result

  • With 10 threads → Works fine
  • With 50,000 threads → Likely error:

java.lang.OutOfMemoryError: unable to create new native thread


Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread


Why Does Thread Creation Fail?

When creating a thread:

  • JVM calls native OS API (pthread_create)
  • Each thread consumes ~1MB stack memory
  • OS enforces thread limits per process

Even if heap memory is available, failure occurs due to:

  • Native memory exhaustion
  • OS thread limits

Java Platform Thread Limits: A Quick Comparison


Resource

Platform Thread

Virtual Thread

Memory per Thread

~1MB

Few KB

Max Threads

~8,000–15,000

1,000,000+

Blocking Cost

High

Minimal

OS Thread Dependency

Yes

No (carrier thread)

Creation Speed

Slow

Fast


Tuning Tips: Can We Create More Platform Threads?


Yes, but with caveats.

Use JVM Flags


 java -Xss256k InboundOutboundTaskDemo
 

This reduces thread stack size to 256KB (vs 1MB default), allowing more threads.


Use Thread Pools

Instead of raw new Thread(), prefer:


 ExecutorService executor = Executors.newFixedThreadPool(200);
 

But even with thread pools, you’re limited by blocked threads during I/O calls.

  • Reuses threads
  • But blocking still exists

 Related: Thread Pool in Java

Alternative: Virtual Threads (Project Loom)

Java 21 introduced virtual threads as a preview feature. These threads are:

  • Lightweight
  • Not backed by OS threads
  • Scalable to millions of concurrent tasks

Stay tuned — in the next post, we’ll rewrite this same example using virtual threads and compare memory usage, performance, and thread behavior.

Advantages and Disadvantages of Platform Threads

 Pros

  • Mature and stable
  • Good for CPU-bound tasks
  • Full support with debugging tools

Cons

  • High memory usage
  • Poor fit for high-concurrency I/O
  • Blocking is expensive

When Should You Use Platform Threads?

 Use When:

  • CPU-bound workloads
  • Limited concurrency
  • Need deep tooling support

Avoid When:

  • Building high-throughput microservices
  • Heavy blocking I/O operations
  • Handling hundreds of thousands of users

Helpful Links


Java Virtual Threads Tutorial (coming soon)


Final Thoughts

Platform threads are powerful — but expensive.

They struggle with modern I/O-heavy workloads, making them less suitable for high-scale systems.

Their limitations led to the evolution of:

Virtual Threads — the future of Java concurrency


No comments:

Post a Comment

Please do not add any spam links in the comments section.