Platform Thread For Blocking Task

ID

java.platform_thread_for_blocking_task

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Efficiency

Language

Java

Tags

concurrency, efficiency

Description

Reports new Thread(task) when task’s body contains a heavy blocking operation from a configurable list — `Thread.sleep, blocking stream or socket I/O, a synchronous HTTP client send. The task is only inspected when it is written directly at the call site, as a lambda or an anonymous Runnable; a method reference or a variable holding the task is left alone. ExecutorService submissions are out of scope, since whether the backing executor uses virtual or platform threads cannot be traced back from the submission call alone.

Rationale

A platform thread that spends most of its life waiting on I/O still occupies an OS thread for the whole wait, and the OS can only host so many of those at once. A virtual thread unmounts from its carrier at the exact point it blocks, freeing that OS thread for other work, which makes it the cheaper choice for exactly this shape of task — the code is not wrong, it is just a more expensive way to run it.

new Thread(() -> {
  try {
    Thread.sleep(1000);
  } catch (InterruptedException e) {
    throw new RuntimeException(e);
  }
}).start();

Remediation

Start the same task on a virtual thread instead.

Thread.ofVirtual().start(() -> {
  try {
    Thread.sleep(1000);
  } catch (InterruptedException e) {
    throw new RuntimeException(e);
  }
});

Configuration

Property Default Meaning

blockingCalls

Thread.sleep, stream/socket I/O, HttpClient.send

fully.Qualified.Type.method entries; a call matches only when its resolved receiver type and method name together equal one of these exactly.

© 2026 Xygeni. All rights reserved