Sleep and Yield Methods in Java – Complete Guide

Overview

The sleep() and yield() methods are used for thread management in Java. They help in controlling thread execution and resource sharing.

1. Thread.sleep() Method

Basic sleep() Usage

public class SleepBasic {
public static void main(String[] args) {
System.out.println("Program started at: " + java.time.LocalTime.now());
try {
// Sleep for 2 seconds
System.out.println("Going to sleep for 2 seconds...");
Thread.sleep(2000); // 2000 milliseconds = 2 seconds
System.out.println("Woke up at: " + java.time.LocalTime.now());
// Sleep for 500 milliseconds
System.out.println("Sleeping for 500 ms...");
Thread.sleep(500);
System.out.println("Woke up again at: " + java.time.LocalTime.now());
} catch (InterruptedException e) {
System.out.println("Sleep was interrupted: " + e.getMessage());
}
}
}

sleep() with Different Time Units

public class SleepTimeUnits {
public static void main(String[] args) {
System.out.println("=== Different Sleep Durations ===");
try {
// Sleep for seconds
System.out.println("Sleeping for 3 seconds...");
Thread.sleep(3000);
System.out.println("Awake!");
// Sleep for milliseconds
System.out.println("Sleeping for 1500 milliseconds...");
Thread.sleep(1500);
System.out.println("Awake!");
// Sleep for minutes (converted to milliseconds)
System.out.println("Sleeping for 10 seconds (simulating minutes)...");
Thread.sleep(10 * 1000); // 10 seconds instead of 10 minutes for demo
System.out.println("Awake after '10 minutes'!");
} catch (InterruptedException e) {
System.out.println("Sleep interrupted: " + e.getMessage());
}
}
// Utility method for readable sleep calls
public static void sleepSeconds(int seconds) {
try {
Thread.sleep(seconds * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Sleep was interrupted", e);
}
}
public static void sleepMillis(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Sleep was interrupted", e);
}
}
}

sleep() in Multiple Threads

public class SleepMultipleThreads {
static class SleepingThread extends Thread {
private String name;
private int sleepTime;
public SleepingThread(String name, int sleepTime) {
this.name = name;
this.sleepTime = sleepTime;
}
@Override
public void run() {
System.out.println(name + " started at: " + java.time.LocalTime.now());
try {
// Each thread sleeps for different durations
System.out.println(name + " is sleeping for " + sleepTime + "ms");
Thread.sleep(sleepTime);
System.out.println(name + " woke up at: " + java.time.LocalTime.now());
} catch (InterruptedException e) {
System.out.println(name + " was interrupted: " + e.getMessage());
}
}
}
public static void main(String[] args) {
System.out.println("Main thread started at: " + java.time.LocalTime.now());
// Create multiple threads with different sleep times
Thread t1 = new SleepingThread("Thread-1", 2000);
Thread t2 = new SleepingThread("Thread-2", 3000);
Thread t3 = new SleepingThread("Thread-3", 1000);
// Start all threads
t1.start();
t2.start();
t3.start();
// Wait for all threads to complete
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All threads completed at: " + java.time.LocalTime.now());
}
}

sleep() with Interruption Handling

public class SleepInterruption {
static class InterruptibleTask extends Thread {
private String taskName;
public InterruptibleTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println(taskName + " started");
try {
// Simulate long-running task with sleep
for (int i = 1; i <= 5; i++) {
System.out.println(taskName + " - Step " + i);
Thread.sleep(1000); // Sleep for 1 second between steps
// Check if thread was interrupted during sleep
if (Thread.currentThread().isInterrupted()) {
System.out.println(taskName + " was interrupted during step " + i);
return;
}
}
System.out.println(taskName + " completed successfully");
} catch (InterruptedException e) {
System.out.println(taskName + " was interrupted with exception: " + e.getMessage());
// Restore interrupt status
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
InterruptibleTask task = new InterruptibleTask("LongRunningTask");
System.out.println("Starting task...");
task.start();
// Let the task run for 2.5 seconds then interrupt it
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Interrupting task...");
task.interrupt();
// Wait for task to finish
try {
task.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread completed");
}
}

2. Thread.yield() Method

Basic yield() Usage

public class YieldBasic {
static class YieldingThread extends Thread {
private String name;
private int iterations;
public YieldingThread(String name, int iterations) {
this.name = name;
this.iterations = iterations;
}
@Override
public void run() {
for (int i = 1; i <= iterations; i++) {
System.out.println(name + " - Iteration " + i);
// Yield control to other threads
Thread.yield();
}
System.out.println(name + " completed");
}
}
public static void main(String[] args) {
System.out.println("=== Yield Demonstration ===");
// Create threads with different priorities
YieldingThread t1 = new YieldingThread("Low-Priority-Thread", 5);
YieldingThread t2 = new YieldingThread("High-Priority-Thread", 5);
// Set thread priorities
t1.setPriority(Thread.MIN_PRIORITY);    // Priority 1
t2.setPriority(Thread.MAX_PRIORITY);    // Priority 10
System.out.println("Starting threads...");
t1.start();
t2.start();
// Wait for threads to complete
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread completed");
}
}

yield() vs sleep() Comparison

public class YieldVsSleep {
static class YieldTask extends Thread {
private String name;
public YieldTask(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(name + " - Before yield - Iteration " + i);
Thread.yield(); // Hint to scheduler
System.out.println(name + " - After yield - Iteration " + i);
}
}
}
static class SleepTask extends Thread {
private String name;
public SleepTask(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(name + " - Before sleep - Iteration " + i);
try {
Thread.sleep(10); // Guaranteed to sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " - After sleep - Iteration " + i);
}
}
}
public static void main(String[] args) {
System.out.println("=== Yield vs Sleep Comparison ===");
System.out.println("\n--- Using Yield ---");
Thread y1 = new YieldTask("Yield-Thread-1");
Thread y2 = new YieldTask("Yield-Thread-2");
y1.start();
y2.start();
try {
y1.join();
y2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\n--- Using Sleep ---");
Thread s1 = new SleepTask("Sleep-Thread-1");
Thread s2 = new SleepTask("Sleep-Thread-2");
s1.start();
s2.start();
try {
s1.join();
s2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\nComparison completed");
}
}

3. Practical Examples

Rate Limiting with sleep()

public class RateLimiting {
static class RateLimitedService {
private final long minIntervalMs;
private long lastCallTime;
public RateLimitedService(long minIntervalMs) {
this.minIntervalMs = minIntervalMs;
this.lastCallTime = 0;
}
public void callService(String request) {
long currentTime = System.currentTimeMillis();
long timeSinceLastCall = currentTime - lastCallTime;
// If called too soon, sleep for remaining time
if (timeSinceLastCall < minIntervalMs) {
long sleepTime = minIntervalMs - timeSinceLastCall;
System.out.println("Rate limit exceeded. Sleeping for " + sleepTime + "ms");
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// Execute the service call
System.out.println("Processing: " + request + " at " + 
java.time.LocalTime.now());
lastCallTime = System.currentTimeMillis();
}
}
public static void main(String[] args) {
// Create service that can only be called once per second
RateLimitedService service = new RateLimitedService(1000);
System.out.println("=== Rate Limiting Demo ===");
// Simulate rapid calls
for (int i = 1; i <= 5; i++) {
service.callService("Request-" + i);
}
System.out.println("All requests processed");
}
}

Producer-Consumer with sleep() for Timing

import java.util.*;
import java.util.concurrent.*;
public class ProducerConsumerWithSleep {
static class SharedBuffer {
private Queue<Integer> buffer = new LinkedList<>();
private final int capacity;
public SharedBuffer(int capacity) {
this.capacity = capacity;
}
public synchronized void produce(int value) throws InterruptedException {
while (buffer.size() == capacity) {
System.out.println("Buffer full, producer waiting...");
wait();
}
buffer.add(value);
System.out.println("Produced: " + value + " | Buffer size: " + buffer.size());
notifyAll();
}
public synchronized int consume() throws InterruptedException {
while (buffer.isEmpty()) {
System.out.println("Buffer empty, consumer waiting...");
wait();
}
int value = buffer.remove();
System.out.println("Consumed: " + value + " | Buffer size: " + buffer.size());
notifyAll();
return value;
}
}
static class Producer extends Thread {
private SharedBuffer buffer;
private int itemsToProduce;
public Producer(SharedBuffer buffer, int itemsToProduce) {
this.buffer = buffer;
this.itemsToProduce = itemsToProduce;
}
@Override
public void run() {
try {
for (int i = 1; i <= itemsToProduce; i++) {
buffer.produce(i);
// Simulate production time with sleep
Thread.sleep(new Random().nextInt(500) + 100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
static class Consumer extends Thread {
private SharedBuffer buffer;
private int itemsToConsume;
public Consumer(SharedBuffer buffer, int itemsToConsume) {
this.buffer = buffer;
this.itemsToConsume = itemsToConsume;
}
@Override
public void run() {
try {
for (int i = 1; i <= itemsToConsume; i++) {
buffer.consume();
// Simulate consumption time with sleep
Thread.sleep(new Random().nextInt(800) + 200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Producer-Consumer with Sleep ===");
SharedBuffer buffer = new SharedBuffer(3);
Producer producer = new Producer(buffer, 10);
Consumer consumer = new Consumer(buffer, 10);
producer.start();
consumer.start();
producer.join();
consumer.join();
System.out.println("Producer-Consumer completed");
}
}

CPU Intensive Task with yield()

public class CPUIntensiveWithYield {
static class CPUIntensiveTask extends Thread {
private String name;
private int computations;
private boolean useYield;
public CPUIntensiveTask(String name, int computations, boolean useYield) {
this.name = name;
this.computations = computations;
this.useYield = useYield;
}
@Override
public void run() {
long startTime = System.currentTimeMillis();
for (int i = 0; i < computations; i++) {
// Simulate CPU-intensive computation
double result = Math.sqrt(Math.pow(i, 3) + Math.pow(i, 2) + i);
if (useYield && i % 1000 == 0) {
// Yield every 1000 computations to be polite
Thread.yield();
}
}
long endTime = System.currentTimeMillis();
System.out.println(name + " completed in " + (endTime - startTime) + "ms");
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== CPU Intensive Tasks with Yield ===");
// Without yield
System.out.println("\n--- Without Yield ---");
CPUIntensiveTask task1 = new CPUIntensiveTask("Task-No-Yield", 1000000, false);
CPUIntensiveTask task2 = new CPUIntensiveTask("Task-No-Yield", 1000000, false);
task1.start();
task2.start();
task1.join();
task2.join();
// With yield
System.out.println("\n--- With Yield ---");
CPUIntensiveTask task3 = new CPUIntensiveTask("Task-With-Yield", 1000000, true);
CPUIntensiveTask task4 = new CPUIntensiveTask("Task-With-Yield", 1000000, true);
task3.start();
task4.start();
task3.join();
task4.join();
System.out.println("\nComparison completed");
}
}

4. Advanced Examples

Scheduled Task Execution

public class ScheduledTasks {
static class ScheduledTask extends Thread {
private String taskName;
private long intervalMs;
private int executions;
private volatile boolean running = true;
public ScheduledTask(String taskName, long intervalMs, int executions) {
this.taskName = taskName;
this.intervalMs = intervalMs;
this.executions = executions;
}
public void stopTask() {
running = false;
interrupt(); // Interrupt if sleeping
}
@Override
public void run() {
int count = 0;
while (running && count < executions) {
count++;
// Execute task
System.out.println(taskName + " executed #" + count + " at " + 
java.time.LocalTime.now());
// Sleep until next execution
if (running && count < executions) {
try {
Thread.sleep(intervalMs);
} catch (InterruptedException e) {
System.out.println(taskName + " was interrupted");
break;
}
}
}
System.out.println(taskName + " completed after " + count + " executions");
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Scheduled Tasks Demo ===");
// Create tasks with different intervals
ScheduledTask task1 = new ScheduledTask("Fast-Task", 1000, 5);    // 1 second interval
ScheduledTask task2 = new ScheduledTask("Slow-Task", 3000, 3);    // 3 second interval
task1.start();
task2.start();
// Let tasks run for a while
Thread.sleep(10000);
// Stop tasks
System.out.println("Stopping tasks...");
task1.stopTask();
task2.stopTask();
task1.join();
task2.join();
System.out.println("All tasks stopped");
}
}

Animation Loop with sleep()

public class AnimationLoop {
static class Animation extends Thread {
private volatile boolean running = true;
private int frameRate; // Frames per second
private String[] frames;
private int currentFrame = 0;
public Animation(int frameRate, String[] frames) {
this.frameRate = frameRate;
this.frames = frames;
}
public void stopAnimation() {
running = false;
interrupt();
}
@Override
public void run() {
long frameInterval = 1000 / frameRate; // ms per frame
long nextFrameTime = System.currentTimeMillis();
while (running) {
// Display current frame
System.out.print("\r" + frames[currentFrame]);
currentFrame = (currentFrame + 1) % frames.length;
// Calculate next frame time
nextFrameTime += frameInterval;
long sleepTime = nextFrameTime - System.currentTimeMillis();
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
System.out.println("\nAnimation interrupted");
break;
}
}
}
System.out.println("\nAnimation stopped");
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Animation Loop Demo ===");
String[] spinnerFrames = {"|", "/", "-", "\\"};
Animation spinner = new Animation(10, spinnerFrames);
System.out.print("Loading: ");
spinner.start();
// Let animation run for 5 seconds
Thread.sleep(5000);
spinner.stopAnimation();
spinner.join();
System.out.println("Demo completed");
}
}

5. Best Practices and Common Pitfalls

Best Practices Examples

public class SleepYieldBestPractices {
// 1. Always handle InterruptedException properly
static class ProperInterruptionHandling extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
// Do some work
System.out.println("Working...");
Thread.sleep(1000);
} catch (InterruptedException e) {
// Restore interrupt status and exit
System.out.println("Thread interrupted, cleaning up...");
Thread.currentThread().interrupt();
break;
}
}
System.out.println("Thread exiting gracefully");
}
}
// 2. Use sleep for timing, not for synchronization
static class ProperSynchronization {
private final Object lock = new Object();
private boolean dataReady = false;
public void waitForData() throws InterruptedException {
synchronized (lock) {
while (!dataReady) {
lock.wait(); // Use wait() instead of sleep() for coordination
}
// Process data
}
}
public void setDataReady() {
synchronized (lock) {
dataReady = true;
lock.notifyAll();
}
}
}
// 3. Avoid busy waiting - use sleep instead
static class AvoidBusyWaiting {
private volatile boolean condition = false;
// BAD: Busy waiting
public void badWaitForCondition() {
while (!condition) {
// Empty loop - wastes CPU cycles
}
}
// GOOD: Using sleep
public void goodWaitForCondition() throws InterruptedException {
while (!condition) {
Thread.sleep(100); // Check condition periodically
}
}
}
// 4. Use yield() for cooperative multitasking in CPU-intensive tasks
static class CooperativeTask extends Thread {
private String name;
private int workUnits;
public CooperativeTask(String name, int workUnits) {
this.name = name;
this.workUnits = workUnits;
}
@Override
public void run() {
for (int i = 0; i < workUnits; i++) {
// Simulate CPU work
performComputation(i);
// Yield periodically to be polite to other threads
if (i % 100 == 0) {
Thread.yield();
}
}
System.out.println(name + " completed");
}
private void performComputation(int i) {
// Simulate some computation
Math.sqrt(i * i + i);
}
}
// 5. Use TimeUnit for readable sleep calls
static class ReadableSleep {
public void demonstrateTimeUnit() throws InterruptedException {
// More readable than Thread.sleep(5000)
java.util.concurrent.TimeUnit.SECONDS.sleep(5);
java.util.concurrent.TimeUnit.MILLISECONDS.sleep(500);
java.util.concurrent.TimeUnit.MINUTES.sleep(1); // In real code, not demo
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Best Practices Demo ===");
// Demonstrate proper interruption handling
System.out.println("\n1. Proper Interruption Handling:");
ProperInterruptionHandling thread = new ProperInterruptionHandling();
thread.start();
Thread.sleep(2500);
thread.interrupt();
thread.join();
// Demonstrate cooperative tasks
System.out.println("\n2. Cooperative Multitasking:");
CooperativeTask task1 = new CooperativeTask("Coop-Task-1", 1000);
CooperativeTask task2 = new CooperativeTask("Coop-Task-2", 1000);
task1.start();
task2.start();
task1.join();
task2.join();
System.out.println("\nAll best practices demonstrated");
}
}

Common Pitfalls to Avoid

public class SleepYieldPitfalls {
// 1. Pitfall: Assuming sleep() is precise
static class PreciseTiming {
public void inaccurateTimer() throws InterruptedException {
long start = System.currentTimeMillis();
// Sleep for exactly 1 second? Not guaranteed!
Thread.sleep(1000);
long end = System.currentTimeMillis();
long actualSleep = end - start;
System.out.println("Requested sleep: 1000ms, Actual sleep: " + actualSleep + "ms");
}
public void betterTimer() throws InterruptedException {
long desiredEnd = System.currentTimeMillis() + 1000;
while (System.currentTimeMillis() < desiredEnd) {
long remaining = desiredEnd - System.currentTimeMillis();
if (remaining > 0) {
Thread.sleep(remaining);
}
}
}
}
// 2. Pitfall: Not handling spurious wakeups
static class SpuriousWakeup {
private final Object lock = new Object();
private boolean condition = false;
public void badWait() throws InterruptedException {
synchronized (lock) {
if (!condition) {
lock.wait(); // Might wake up without notify!
}
}
}
public void goodWait() throws InterruptedException {
synchronized (lock) {
while (!condition) { // Always use while loop
lock.wait();
}
}
}
}
// 3. Pitfall: Using yield() for synchronization
static class YieldSynchronization {
private volatile int counter = 0;
// BAD: Using yield for synchronization
public void badIncrement() {
// This doesn't guarantee proper synchronization
counter++;
Thread.yield();
}
// GOOD: Proper synchronization
public synchronized void goodIncrement() {
counter++;
}
}
// 4. Pitfall: Ignoring interrupt status
static class IgnoreInterrupt {
public void badSleepMethod() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// BAD: Just ignoring the exception
System.out.println("Interrupted, but continuing...");
}
}
public void goodSleepMethod() throws InterruptedException {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// GOOD: Restore interrupt status and handle appropriately
Thread.currentThread().interrupt();
throw e; // Or return, depending on context
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Common Pitfalls ===");
PreciseTiming timer = new PreciseTiming();
timer.inaccurateTimer();
System.out.println("\nPitfalls demonstrated");
}
}

Key Differences Summary

Aspectsleep()yield()
GuaranteeGuaranteed to sleep for at least specified timeHint to scheduler, no guarantees
Thread StateChanges to TIMED_WAITINGRemains in RUNNABLE
InterruptionThrows InterruptedExceptionNo exception thrown
Use CaseTiming, delays, rate limitingCooperative multitasking
CPU UsageReleases CPU completelyMay immediately regain CPU
PrecisionNot precise (depends on OS)No timing involved

Best Practices Summary

  1. Always handle InterruptedException - restore interrupt status
  2. Use sleep() for timing, not for thread coordination
  3. Use yield() sparingly - mostly for CPU-intensive cooperative tasks
  4. Prefer TimeUnit for more readable sleep calls
  5. Never rely on sleep() precision for critical timing
  6. Avoid busy waiting - use sleep with periodic checks
  7. Don't use yield() for synchronization - use proper synchronization primitives

Understanding when and how to use sleep() and yield() is crucial for writing efficient and responsive multi-threaded Java applications.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper