Skip to content

Threads and Tasks

A task is a unit of work. A thread is an execution mechanism with a call stack. Separating the two lets an executor decide where and when tasks run.

Platform and virtual threads

Platform threads are commonly mapped to operating-system threads. Virtual threads are Java threads scheduled by the runtime and are designed to support large numbers of mostly blocking tasks with a thread-per-task style.

Virtual threads do not make CPU work faster and do not remove the need to bound scarce resources such as database connections. The pools and bounded resources guide explains why thread scalability does not create downstream capacity. Long blocking operations may free a carrier thread, but the external service remains a capacity limit.

try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
    Future<String> first = executor.submit(() -> fetch("https://example.com/a"));
    Future<String> second = executor.submit(() -> fetch("https://example.com/b"));
    consume(first.get(), second.get());
}

Cancellation and interruption

Interruption is a cooperative request. Blocking Java methods may throw InterruptedException; computation should periodically check interruption when appropriate. If a layer cannot propagate the checked exception, it normally restores status before returning or translating:

catch (InterruptedException exception) {
    Thread.currentThread().interrupt();
    throw new IllegalStateException("operation interrupted", exception);
}

A cancellation policy must define ownership, cleanup, deadlines, and what result callers observe. A total deadline must include queueing and retry delays. Forcibly stopping arbitrary code cannot generally preserve its invariants.