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
| Aspect | sleep() | yield() |
|---|---|---|
| Guarantee | Guaranteed to sleep for at least specified time | Hint to scheduler, no guarantees |
| Thread State | Changes to TIMED_WAITING | Remains in RUNNABLE |
| Interruption | Throws InterruptedException | No exception thrown |
| Use Case | Timing, delays, rate limiting | Cooperative multitasking |
| CPU Usage | Releases CPU completely | May immediately regain CPU |
| Precision | Not precise (depends on OS) | No timing involved |
Best Practices Summary
- Always handle InterruptedException - restore interrupt status
- Use sleep() for timing, not for thread coordination
- Use yield() sparingly - mostly for CPU-intensive cooperative tasks
- Prefer TimeUnit for more readable sleep calls
- Never rely on sleep() precision for critical timing
- Avoid busy waiting - use sleep with periodic checks
- 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.