Busy Waiting, Polling, and Blocking
Revised October 19, 2026. What changed
A tight loop repeatedly checking a condition consumes execution time while it waits. That is busy waiting. A loop that calls Thread.sleep between checks is polling: it gives up execution during the sleep but trades wake-up delay against repeated checks.
Choose the wait your protocol needs
Spinning can be justified for very short waits in specialized low-level code. Polling can be appropriate when a remote system offers no notification mechanism. For producer–consumer work within a Java process, a BlockingQueue gives explicit waiting and publication semantics.
static void blockingExample() throws InterruptedException {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(2);
AtomicInteger sum = new AtomicInteger();
Thread consumer = new Thread(() -> {
try {
while (true) {
int value = queue.take();
if (value == -1) return; // -1 is outside this example's input domain
sum.addAndGet(value);
}
} catch (InterruptedException interrupted) {
Thread.currentThread().interrupt();
}
});
consumer.start();
try {
queue.put(2); queue.put(3); queue.put(-1);
consumer.join(2000);
check(!consumer.isAlive() && sum.get() == 5, "queue result or termination");
} finally {
consumer.interrupt(); consumer.join(2000);
}
}
The queue is bounded, so producers wait when it is full. The consumer blocks on take() when it is empty. The sentinel is outside the example’s valid domain and terminates this single consumer. Multiple consumers require an explicit shutdown policy; one sentinel is not enough for an arbitrary worker pool.
Cancellation and visibility are part of the example
The consumer restores its interrupt status and exits if interrupted. The coordinating thread bounds its join and interrupts the consumer during cleanup. Queue operations establish the publication relationship needed to hand off values safely. A plain shared boolean is not a replacement for a specified memory-visibility protocol.
For remote polling, use a deadline, bounded backoff, and cancellation. Measure both request load and detection delay. Replacing a spin with sleep changes the tradeoff; it does not turn polling into event-driven delivery.
The workbench includes the complete LegacyExamples.java program, imports, assertions, and a run command: java LegacyExamples.java with JDK 17 or later. The fragments below are extracted from that same tested source.