线程中的wait()和sleep()有什么区别?

我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?

为什么我们同时使用wait()和sleep()?

它们的实现在较低级别上有什么不同?


当前回答

sleep是Thread的一个方法,wait是Object的一个方法,所以wait/notify是Java中同步共享数据的一种技术(使用monitor),而sleep是线程暂停自身的一种简单方法。

其他回答

等待和睡觉是两回事:

在sleep()中,线程在指定的时间内停止工作。 在wait()中,线程停止工作,直到被等待的对象被通知,通常由其他线程通知。

这里有很多答案,但我找不到任何一个提到的语义区别。

这与线程本身无关;这两种方法都是必需的,因为它们支持非常不同的用例。

sleep()让线程像以前一样进入睡眠状态,它只是打包上下文并在预定义的时间内停止执行。因此,为了在到期时间之前唤醒它,您需要知道Thread引用。这在多线程环境中并不常见。它主要用于时间同步(例如,在3.5秒内醒来)和/或硬编码的公平性(只睡一会儿,让其他线程工作)。

相反,wait()是一种线程(或消息)同步机制,它允许您通知没有存储引用(也没有关心)的线程。您可以将其视为一个发布-订阅模式(wait == subscribe and notify() == publish)。基本上,使用notify()你是在发送一条消息(甚至可能根本没有收到,通常情况下你并不关心)。

总而言之,通常使用sleep()进行时间同步,使用wait()进行多线程同步。

它们可以在底层操作系统中以同样的方式实现,也可以完全不实现(因为以前版本的Java没有真正的多线程;可能一些小的虚拟机也不这样做)。别忘了Java是在VM上运行的,所以你的代码会根据所运行的VM/OS/HW的不同而转换成不同的东西。

Sleep()方法导致当前线程在指定的时间内从运行状态转移到阻塞状态。如果当前线程拥有任何对象的锁,那么它会一直持有它,这意味着其他线程不能在该类对象中执行任何同步方法。

Wait()方法会导致当前线程在指定的时间内进入阻塞状态或直到notify,但在这种情况下,线程会释放对象的锁(这意味着其他线程可以执行调用对象的任何同步方法)。

在研究了wait和sleep之后,我总结了一些不同的关键注意事项,首先看一下使用wait()和sleep()的示例:

例1:使用wait()和sleep():

synchronized(HandObject) {
    while(isHandFree() == false) {
        /* Hand is still busy on happy coding or something else, please wait */
        HandObject.wait();
    }
}

/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
    /* Beer is still coming, not available, Hand still hold glass to get beer,
       don't release hand to perform other task */
    Thread.sleep(5000);
}

/* Enjoy my beer now ^^ */
drinkBeers();

/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
    HandObject.notifyAll();
}

让我们明确一些关键的注意事项:

呼吁: wait():调用当前持有handdobject对象的线程 sleep():在线程上调用执行任务获取啤酒(是类方法,因此影响当前运行的线程) 同步: wait():当同步多线程访问同一对象(HandObject)时(当多个线程之间需要通信时(线程执行编码,线程执行获取啤酒)访问同一对象(HandObject) sleep():当等待状态继续执行时(等待啤酒可用) 持有锁: wait():释放锁,让其他对象有机会执行(HandObject是空闲的,你可以做其他工作) sleep():保持锁至少t次(或直到中断)(我的工作仍然没有完成,我继续持有锁,等待一些条件继续) 唤醒条件: wait():直到调用notify(), notifyAll()从对象 Sleep():直到至少超时或调用中断 最后一点是当estani表示:

通常使用sleep()进行时间同步,使用wait()进行时间同步 multi-thread-synchronization。

如果我说错了,请指正。

关于睡眠不释放锁,等待释放锁的例子

这里有两个类:

Main:包含Main方法和两个线程。 单例:这是一个单例类,有两个静态方法getInstance()和getInstance(boolean isWait)。 公共类Main { private static singletonA = null; private static Singleton singletonB = null; public static void main(String[] args)抛出InterruptedException { 线程threadA =新线程(){ @Override 公共无效运行(){ singletonA = Singleton.getInstance(true); } }; 线程threadB = new Thread() { @Override 公共无效运行(){ singletonB = Singleton.getInstance(); while (singletonA == null) { system . out。println("SingletonA still null"); } if (singletonA == singletonB) { system . out。println("两个单例是相同的"); }其他{ system . out。println("两个单例不相同"); } } }; threadA.start (); threadB.start (); } }

and

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Using wait
                        Thread.sleep(500);// Using Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

现在运行这个例子,你会得到以下输出:

_instance :null
Both singleton are same

这里由线程a和线程b创建的单例实例是相同的。这意味着线程b在外面等待,直到线程a释放它的锁。

现在通过注释Thread.sleep(500)来更改Singleton.java;Singleton.class.wait(500);. 这里因为Singleton.class.wait(500);方法threadA将释放所有获取锁并进入“Non Runnable”状态,threadB将获得change进入synchronized块。

现在再运行一次:

SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

这里由线程a和线程b创建的单例实例是不一样的,因为线程b得到了进入同步块的变化,500毫秒后,线程a从它的最后一个位置开始,并创建了一个新的单例对象。