Java中wait和sleep的区别

2023/06/07

1. 概述

在这篇简短的文章中,我们将看看Java核心中的标准sleep()和wait()方法,并介绍它们之间的异同。

2. wait和sleep的一般区别

简单地说,wait()是一个用于线程同步的实例方法

它可以在任何对象上调用,因为它是在java.lang.Object中定义的,但只能从同步代码块调用它。它释放对象上的锁,以便另一个线程可以进入并获取锁。

另一方面,Thread.sleep()是一个可以从任何上下文调用的静态方法。Thread.sleep()暂停当前线程,不释放任何锁

下面是对这两个核心API的一个非常简单的初步介绍:

public class WaitSleepExample {
    private static final Logger LOG = LoggerFactory.getLogger(WaitSleepExample.class);
    private static final Object LOCK = new Object();

    public static void main(String... args) throws InterruptedException {
        sleepWaitInSynchronizedBlocks();
    }

    private static void sleepWaitInSynchronizedBlocks() throws InterruptedException {
        Thread.sleep(1000); // called on the thread
        LOG.debug("Thread '" + Thread.currentThread().getName() + "' is woken after sleeping for 1 second");

        synchronized (LOCK) {
            LOCK.wait(1000); // called on the object, synchronization required
            LOG.debug("Object '" + LOCK + "' is woken after waiting for 1 second");
        }
    }
}

运行以上代码的输出为:

...... >>> Thread 'main' is woken after sleeping for 1 second 
...... >>> Object 'java.lang.Object@1786dec2' is woken after waiting for 1 second 

3. 唤醒wait和sleep

当我们使用sleep()方法时,线程会在指定的时间间隔后启动,除非它被中断。

对于wait(),唤醒过程要复杂一些。我们可以通过在正在等待的监视器上调用notify()或notifyAll()方法来唤醒线程。

如果要唤醒所有处于等待状态的线程,可以使用notifyAll()。与wait()方法本身类似,必须从同步上下文中调用notify()和notifyAll()。

例如,以下是wait的使用方式:

public class ThreadA {
    private static final Logger LOG = LoggerFactory.getLogger(ThreadA.class);
    private static final ThreadB b = new ThreadB();

    public static void main(String... args) throws InterruptedException {
        b.start();

        synchronized (b) {
            while (b.sum == 0) {
                LOG.debug("Waiting for ThreadB to complete...");
                b.wait();
            }
            LOG.debug("ThreadB has completed. Sum from that thread is: " + b.sum);
        }
    }
}

然后,另一个线程就可以通过在监视器上调用notify()来唤醒等待的线程

class ThreadB extends Thread {
    int sum;

    @Override
    public void run() {
        synchronized (this) {
            int i = 0;
            while (i < 100000) {
                sum += i;
                i++;
            }
            notify();
        }
    }
}

运行以上代码的输出为:

...... >>> Waiting for ThreadB to complete... 
...... >>> ThreadB has completed. Sum from that thread is: 704982704

4. 总结

本文是对Java中wait和sleep语义的快速入门。

通常,我们应该使用sleep()来控制一个线程的执行时间,而wait()用于多线程同步。当然,在充分理解了基础知识之后,还有很多东西值得探索。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章