61. sleep() 和 wait() 有什么区别?

sleep()wait() 方法在Java中被广泛用于线程控制,它们都可以让线程暂停执行一段时间,但它们之间存在一些重要的区别:

  1. 所属类
    • sleep()Thread 类的静态方法。
    • wait()Object 类的方法。
  2. 使用范围
    • sleep() 可以在任何地方使用,因为它属于 Thread 类。
    • wait() 必须在同步上下文中调用,即必须在获取了对象锁的代码块中使用,通常用在对象的同步方法或同步代码块中。
  3. 释放锁
    • sleep() 不会释放当前线程所持有的锁资源。
    • wait() 会立即释放当前线程持有的锁资源,直到另一个线程调用同一个对象的 notify()notifyAll() 方法来唤醒它。
  4. 精度
    • sleep() 方法通常用于短时间等待,它能够指定具体的等待时间(毫秒或纳秒),并且能够较为准确地控制唤醒时间。
    • wait() 方法没有参数,它通常用于线程间的通信,等待其他线程的通知,等待的时间是不确定的。
  5. 方法调用
    • 调用 sleep() 方法不需要当前线程拥有任何锁。
    • 调用 wait() 方法必须在拥有对象的锁的情况下进行。
  6. 唤醒方式
    • sleep() 方法到达指定时间后自动唤醒。
    • wait() 方法需要其他线程调用对象的 notify()notifyAll() 来唤醒。

以下是 sleep()wait() 的代码示例:

// sleep() 方法示例
Thread thread = new Thread(() -> {
    try {
        Thread.sleep(1000); // 休眠1秒
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("线程被唤醒");
});

// wait() 方法示例
Object lock = new Object();
new Thread(() -> {
    synchronized (lock) {
        try {
            lock.wait(); // 等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程通过notify()被唤醒");
    }
}).start();

// 在另一个线程中唤醒wait()的线程
new Thread(() -> {
    synchronized (lock) {
        lock.notify(); // 唤醒等待的线程
    }
}).start();

在使用 wait()notify() 时,通常需要紧密协调以确保线程安全,而 sleep() 更适合于简单的定时等待场景。

62. notify() 和 notifyAll()有什么区别?

notify()notifyAll() 是Java中用于线程同步的Object类的方法,它们用于唤醒等待同一共享资源的线程。

notify() 方法:

  • 它会随机选择一个在对象监视器上等待的线程,并通知该线程,使其从等待状态进入可运行状态。
  • 选择哪个线程是由JVM决定的,并且是不可预测的。
  • 如果没有线程在等待,notify()调用不会有任何效果。
  • 在被通知的线程重新获得对共享资源的访问权限并退出同步块之前,其他线程仍然处于阻塞状态。

notifyAll() 方法:

  • 它会通知所有在该对象监视器上等待的线程,使它们从等待状态进入可运行状态。
  • 这样,所有等待的线程都有机会获取共享资源,并继续执行。
  • 如果没有线程在等待,notifyAll()调用同样不会有任何效果。

以下是这两个方法的使用场景和区别的总结:

以下是这两个方法的一个简单代码示例:

public class SharedObject {
    public synchronized void doSomething() {
        // 假设这里是需要共享资源的代码块
        // ...
        // 通知正在等待的线程(单个或所有)
        this.notify(); // 或者 this.notifyAll();
    }
}

public class ThreadA extends Thread {
    private SharedObject sharedObject;
    
    public ThreadA(SharedObject sharedObject) {
        this.sharedObject = sharedObject;
    }
    
    @Override
    public void run() {
        synchronized(sharedObject) {
            try {
                // 等待,直到被notify()或notifyAll()唤醒
                sharedObject.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 执行共享资源操作
            sharedObject.doSomething();
        }
    }
}

在以上代码中,notify()notifyAll()可以在doSomething()方法中互换使用,但它们的效果和适用场景会有明显的不同。

有帮助请点赞收藏呀~

领【150 道精选 Java 高频面试题】请 go 公众号:码路向前 。

04-18 08:50