杰瑞科技汇

Java中sleep和join方法有何区别?

Of course! sleep() and join() are two fundamental methods in Java for managing thread execution. They are often discussed together because they both involve pausing or waiting for threads, but they work in very different ways.

Java中sleep和join方法有何区别?-图1
(图片来源网络,侵删)

Let's break them down one by one and then compare them.


Thread.sleep()

sleep() is a static method of the Thread class. Its primary purpose is to pause the current thread's execution for a specified amount of time.

Key Characteristics:

  • Static Method: You call it on the Thread class itself (Thread.sleep()), not on a specific thread instance (though you can, it's less common).
  • Pauses the Current Thread: It causes the thread that calls the method to enter the TIMED_WAITING state.
  • Does Not Release Locks: Crucially, a sleeping thread does not release any locks it holds on objects. This is a common source of deadlocks if not handled carefully.
  • Can Be Interrupted: If another thread calls the interrupt() method on the sleeping thread, sleep() will throw an InterruptedException. This is the standard way to wake up a sleeping thread prematurely.

Simple Example of sleep():

This example prints a message every second.

public class SleepExample implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 1; i <= 5; i++) {
                System.out.println("Thread " + Thread.currentThread().getName() + " is running. Count: " + i);
                // Pause the current thread for 1000 milliseconds (1 second)
                Thread.sleep(1000); 
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + Thread.currentThread().getName() + " was interrupted.");
            // Restore the interrupted status
            Thread.currentThread().interrupt();
        }
    }
    public static void main(String[] args) {
        Thread thread = new Thread(new SleepExample(), "My-Sleeper-Thread");
        thread.start();
        System.out.println("Main thread started.");
    }
}

Output:

Java中sleep和join方法有何区别?-图2
(图片来源网络,侵删)
Main thread started.
Thread My-Sleeper-Thread is running. Count: 1
Thread My-Sleeper-Thread is running. Count: 2
Thread My-Sleeper-Thread is running. Count: 3
Thread My-Sleeper-Thread is running. Count: 4
Thread My-Sleeper-Thread is running. Count: 5

thread.join()

join() is an instance method of the Thread class. Its purpose is to wait for a specific thread to finish its execution.

Key Characteristics:

  • Instance Method: You call it on a specific Thread object (e.g., myThread.join()).
  • Waits for Another Thread: The thread that calls join() will pause its own execution until the thread it's waiting for (myThread) has completed (i.e., its run() method has finished).
  • Releases Locks: When a thread is waiting on join(), it releases any locks it holds, allowing other threads to run. This is a key difference from sleep().
  • Can Be Interrupted: Like sleep(), join() can also be interrupted, throwing an InterruptedException.
  • Overloaded Methods:
    • join(): Waits indefinitely for the thread to die.
    • join(long millis): Waits for at most millis milliseconds.
    • join(long millis, int nanos): Waits for at most millis milliseconds and nanos nanoseconds.

Simple Example of join():

This example shows the main thread waiting for the worker thread to complete before it proceeds.

public class JoinExample implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " has started.");
        try {
            // Simulate a task that takes 2 seconds
            Thread.sleep(2000); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " has finished.");
    }
    public static void main(String[] args) throws InterruptedException {
        Thread workerThread = new Thread(new JoinExample(), "Worker-Thread");
        workerThread.start();
        System.out.println("Main thread is about to wait for the worker thread.");
        // The main thread will pause here until workerThread is dead
        workerThread.join(); 
        System.out.println("Main thread has resumed after the worker thread finished.");
    }
}

Output:

Main thread is about to wait for the worker thread.
Worker-Thread has started.
Worker-Thread has finished. // This prints after 2 seconds
Main thread has resumed after the worker thread finished.

Comparison: sleep() vs. join()

Feature Thread.sleep() thread.join()
Purpose To pause the current thread for a duration. To wait for a specific thread to terminate.
Method Type Static (Thread.sleep()) Instance (myThread.join())
What it does Puts the calling thread into TIMED_WAITING. Puts the calling thread into WAITING or TIMED_WAITING.
Locks Does not release locks held by the sleeping thread. Releases locks held by the waiting thread.
What it waits for A predefined amount of time. The termination of another thread.
Common Use Case Introducing delays, polling at intervals. Ensuring tasks are executed in a specific order, waiting for results from another thread.
Example Thread.sleep(500); workerThread.join();

Combined Example: Using sleep() and join() Together

This is a very common pattern. You might have multiple "worker" threads, and you want a main thread to start them all and then wait for them all to complete before proceeding.

Java中sleep和join方法有何区别?-图3
(图片来源网络,侵删)
public class CombinedExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Task("Task 1", 1500));
        Thread thread2 = new Thread(new Task("Task 2", 1000));
        Thread thread3 = new Thread(new Task("Task 3", 2000));
        System.out.println("Starting all tasks...");
        thread1.start();
        thread2.start();
        thread3.start();
        System.out.println("Main thread is now waiting for all tasks to complete.");
        try {
            // Wait for each thread to finish. The order of join() calls doesn't
            // guarantee the order of completion, but it does ensure we wait for each one.
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            System.out.println("Main thread was interrupted while waiting.");
            Thread.currentThread().interrupt();
        }
        System.out.println("All tasks have finished. Main thread continues.");
    }
}
class Task implements Runnable {
    private final String name;
    private final long duration;
    public Task(String name, long duration) {
        this.name = name;
        this.duration = duration;
    }
    @Override
    public void run() {
        try {
            System.out.println(name + " has started.");
            // Use sleep() to simulate work
            Thread.sleep(duration);
            System.out.println(name + " has finished after " + duration + "ms.");
        } catch (InterruptedException e) {
            System.out.println(name + " was interrupted.");
            Thread.currentThread().interrupt();
        }
    }
}

Output:

Starting all tasks...
Main thread is now waiting for all tasks to complete.
Task 1 has started.
Task 2 has started.
Task 3 has started.
Task 2 has finished after 1000ms.
Task 1 has finished after 1500ms.
Task 3 has finished after 2000ms.
All tasks have finished. Main thread continues.

Modern Alternatives (Java 8+)

While sleep() and join() are still essential, modern Java offers more powerful and higher-level abstractions for concurrency:

  • java.util.concurrent.ExecutorService: For managing a pool of threads. It provides methods like shutdown() and awaitTermination() which are often cleaner than manually joining multiple threads.
  • CompletableFuture: For composing asynchronous operations. It has methods like thenCombine(), thenAccept(), and join() (a different join()!) that allow you to chain tasks together and handle their results elegantly.
  • java.util.concurrent.CountDownLatch: A utility for one or more threads to wait until a set of operations being performed in other threads completes. This is a more flexible and powerful alternative to join() when you need to wait for a group of tasks.

Summary

  • Use sleep() when you need the current thread to pause for a specific amount of time.
  • Use join() when you need the current thread to wait for another specific thread to finish before it can continue.
  • Remember that sleep() does not release locks, while join() does.
分享:
扫描分享到社交APP
上一篇
下一篇