sleep用法 - thread.sleep java




wait()和sleep()之间的区别 (20)

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

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

为什么我们同时 wait()sleep() :它们的实现在较低的层次上如何变化?


wait()和sleep()之间的区别

  • 基本的区别是wait()来自Objectsleep()Thread静态方法。

  • 主要区别在于wait()释放锁,而sleep()在等待时不释放任何锁。

  • wait()用于进行线程间通信,而sleep()通常用于暂停执行。

  • wait()应该从同步内部调用,否则我们会得到IllegalMonitorStateExceptionsleep()可以在任何地方调用。

  • 要从wait()再次启动线程,必须调用notify()notifyAll() 。 在sleep(),线程在指定的ms / sec间隔后启动。

有助于理解的相似之处

  • 两者都使当前线程进入Not Runnable状态。
  • 两者都是native方法。

睡觉

  • 它导致当前正在执行的线程在特定的时间内休眠。
  • 其准确度取决于系统定时器和调度程序。
  • 它保留它所获取的监视器,所以如果从同步上下文中调用它,则其他线程不能进入该块或方法。
  • 如果我们调用interrupt()方法,它会唤醒睡眠线程。

等待

  • 它导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法
  • 它必须从同步上下文中调用,即从块或方法中调用。它意味着在调用wait()方法之前,当前线程必须锁定该对象。
  • 它释放对它所调用的对象的锁定并将其添加到等待列表中,以便另一个线程可以获取该对象的锁定。

sleep() method causes the current thread to move from running state to block state for a specified time. If the current thread has the lock of any object then it keeps holding it, which means that other threads cannot execute any synchronized method in that class object.

wait() method causes the current thread to go into block state either for a specified time or until notify, but in this case the thread releases the lock of the object (which means that other threads can execute any synchronized methods of the calling object.


sleepThread一种方法, waitObject一种方法,所以wait/notify是一种在Java中使用monitor同步共享数据的技术,但sleep是一种简单的线程暂停方法。


waitsleep方法是非常不同的:

  • sleep没有办法“醒来”,
  • wait在等待期间有一种唤醒方式,通过另一个线程调用notifynotifyAll

想想看,名称在这方面令人困惑; 但是sleep是一个标准名称,并且wait类似Win API中的WaitForSingleObjectWaitForMultipleObjects


Should be called from synchronized block : wait() method is always called from synchronized block ie wait() method needs to lock object monitor before object on which it is called. But sleep() method can be called from outside synchronized block ie sleep() method doesn't need any object monitor.

IllegalMonitorStateException : if wait() method is called without acquiring object lock than IllegalMonitorStateException is thrown at runtime, but sleep() method never throws such exception.

Belongs to which class : wait() method belongs to java.lang.Object class but sleep() method belongs to java.lang.Thread class.

Called on object or thread : wait() method is called on objects but sleep() method is called on Threads not objects.

Thread state : when wait() method is called on object, thread that holded object's monitor goes from running to waiting state and can return to runnable state only when notify() or notifyAll() method is called on that object. And later thread scheduler schedules that thread to go from from runnable to running state. when sleep() is called on thread it goes from running to waiting state and can return to runnable state when sleep time is up.

When called from synchronized block : when wait() method is called thread leaves the object lock. But sleep() method when called from synchronized block or method thread doesn't leaves object lock.

For More Reference


Example about sleep doesn't release lock and wait does

Here there are two classes :

  1. Main : Contains main method and two threads.
  2. Singleton : This is singleton class with two static methods getInstance() and getInstance(boolean isWait).

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }
    

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;

 }
}

Now run this example you will get below output :

_instance :null
Both singleton are same

Here Singleton instances created by threadA and threadB are same. It means threadB is waiting outside until threadA release it's lock.

Now change the Singleton.java by commenting Thread.sleep(500); method and uncommenting Singleton.class.wait(500); 。 Here because of Singleton.class.wait(500); method threadA will release all acquire locks and moves into the “Non Runnable” state, threadB will get change to enter in synchronized block.

Now run again :

SingletonA still null
SingletonA still null
SingletonA still null
_instance :[email protected]
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

Here Singleton instances created by threadA and threadB are NOT same because of threadB got change to enter in synchronised block and after 500 milliseconds threadA started from it's last position and created one more Singleton object.


From oracle documentation page on wait() method of Object :

public final void wait()
  1. Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0) .
  2. The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up
  3. interrupts and spurious wakeups are possible
  4. This method should only be called by a thread that is the owner of this object's monitor

This method throws

  1. IllegalMonitorStateException - if the current thread is not the owner of the object's monitor.

  2. InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.

From oracle documentation page on sleep() method of Thread class:

public static void sleep(long millis)
  1. Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
  2. The thread does not lose ownership of any monitors.

This method throws:

  1. IllegalArgumentException - if the value of millis is negative

  2. InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

Other key difference:

wait() is a non-static method (instance method) unlike static method sleep() (class method).


In my opinion, the main difference between both mechanisms is that sleep/interrupt is the most basic way of handling threads, whereas wait/notify is an abstraction aimed to do thread inter-communication easier. This means that sleep/interrupt can do anything, but that this specific task is harder to do.

Why is wait/notify more suitable? Here are some personal considerations:

  1. It enforces centralization. It allows to coordinate the communication between a group of threads with a single shared object. This simplifies the work a lot.

  2. It enforces synchronization. Because it makes the programmer wrap the call to wait/notify in a synchronized block.

  3. It's independent of the thread origin and number. With this approach you can add more threads arbitrarily without editing the other threads or keeping a track of the existing ones. If you used sleep/interrupt, first you would need to keep the references to the sleeping threads, and then interrupt them one by one, by hand.

An example from the real life that is good to explain this is a classic restaurant and the method that the personnel use to communicate among them: The waiters leave the customer requests in a central place (a cork board, a table, etc.), ring a bell, and the workers from the kitchen come to take such requests. Once that there is any course ready, the kitchen personnel ring the bell again so that the waiters are aware and take them to the customers.


Lets assume you are hearing songs.

As long as the current song is running, the next song wont play, ie Sleep() called by next song

如果你完成了歌曲,它会停止,直到你选择播放按钮(notify())它不会播放,即wait()被当前歌曲调用。

在这两种情况下,歌曲将进入等待状态。


一个wait可以被另一个线程唤醒,这个线程正在等待的监视器上notify ,而sleep不能。 wait (和notify )也必须在监视器对象上synchronized的块中发生,而sleep不会:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

此时当前正在执行的线程等待并释放监视器 。 另一个线程可能会做

synchronized (mon) { mon.notify(); }

(在同一个mon对象上),第一个线程(假设它是在显示器上等待的唯一线程)将唤醒。

如果监视器上有多个线程正在等待,您也可以调用notifyAll - 这将唤醒所有这些线程。 但是,只有其中一个线程能够抓取显示器(请记住wait处于synchronized块中)并继续运行 - 其他线程将被阻止,直到它们可以获取显示器的锁定为止。

另一点是,你调用wait Object本身(即你等待对象的监视器),而你调用Thread sleep

还有一点是,你可以从wait获得虚假的唤醒(即等待恢复的线程没有明显的原因)。 您应该一直wait同时按照以下条件旋转

synchronized {
    while (!condition) { mon.wait(); }
}

从这篇文章: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/ : http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

wait()方法。

1)调用wait()方法的线程释放它保存的锁。

2)其他线程在同一个锁上调用notify()或notifyAll()方法后,线程重新获得锁。

3)wait()方法必须在synchronized块中调用。

4)wait()方法总是在对象上调用。

5)等待线程可以通过调用notify()或notifyAll()方法由其他线程唤醒。

6)要调用wait()方法,线程必须具有对象锁定。

睡眠()方法

1)调用sleep()方法的线程不释放它拥有的锁。

2)可以在synchronized块内或外部调用sleep()方法。

3)sleep()方法总是在线程上调用。

4)睡眠线程不能被其他线程唤醒。 如果这样做,线程将抛出InterruptedException。

5)要调用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();
}

让一些关键说明清楚:

  1. 呼吁
    • wait():在保存HandObject对象的当前线程上调用
    • sleep():调用线程执行任务get beer(是类方法,因此影响当前正在运行的线程)
  2. 同步
    • wait():当同步多线程访问时相同Object(HandObject)(当需要多个线程之间的通信(线程执行编码,线程执行get啤酒)访问同一对象时HandObject)
    • 睡眠():当等待条件继续执行时(等待啤酒可用)
  3. 保持锁定
    • wait():释放其他对象的锁有机会执行(HandObject是免费的,你可以做其他工作)
    • 睡眠():保持锁定至少t次(或直到中断)(我的工作还没有完成,我继续保持锁定并等待一些条件继续)
  4. 唤醒条件
    • wait():直到从对象调用notify(),notifyAll()
    • 睡眠():直到至少时间到期或呼叫中断
  5. 最后一点是 estani表示时使用

您通常使用sleep()进行时间同步,并使用wait()进行多线程同步。

如果我错了,请纠正我。


在这里,我列出了wait()sleep()方法之间的几个重要区别。
PS: 同时点击链接查看图书馆代码(内部工作,只是稍微玩一下以便更好地理解)。

wait()

  1. wait()方法释放锁。
  2. wait()Object类的方法。
  3. wait()是非静态方法 - public final void wait() throws InterruptedException { //...}
  4. wait()应该通过notify()notifyAll()方法来通知。
  5. wait()方法需要从循环中调用以处理虚警。

  6. wait()方法必须从同步上下文(即同步方法或块)中IllegalMonitorStateException ,否则将抛出IllegalMonitorStateException

sleep()

  1. sleep()方法不释放锁。
  2. sleep()java.lang.Thread类的方法。
  3. sleep()是静态方法 - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. 在指定的时间之后, sleep()完成。
  5. sleep()最好不要从循环调用(即见下面的代码 )。
  6. sleep()可以从任何地方调用。 没有具体要求。

参考: 等待和睡眠之间的区别

用于调用wait和sleep方法的代码片段

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}


来源: http://www.jguru.com/faq/view.jsp?EID=47127 : http://www.jguru.com/faq/view.jsp?EID=47127

sleep将当前线程发送到“Not Runnable”状态一段时间。 线程保持已经获得的监视器 - 也就是说,如果线程当前处于同步块或方法中,则其他线程不能进入该块或方法。 如果另一个线程调用t.interrupt()它会唤醒睡眠线程。

请注意,sleep是一种静态方法,这意味着它总是影响当前线程(执行睡眠方法的线程)。 一个常见的错误是调用t.sleep() ,其中t是不同的线程; 即使如此,它是当前的线程,将睡眠,而不是T线程。

t.suspend()已弃用。 使用它可以暂停当前线程以外的线程。 暂停的线程保留所有的监视器,并且由于此状态不可中断,因此容易出现死锁。

wait将当前线程发送到“Not Runnable”状态,如sleep() ,但带有扭曲。 等待是在一个对象上调用的,而不是一个线程; 我们称这个对象为“锁定对象”。 在lock.wait()之前,当前线程必须在锁对象上同步; wait()然后释放此锁,并将该线程添加到与该锁关联的“等待列表”。 稍后,另一个线程可以在同一个锁对象上同步并调用lock.notify() 。 这唤醒了原来的等待线程。 基本上, wait() / notify()就像sleep() / interrupt() ,只有活动线程不需要直接指向睡眠线程的指针,而只需要指向共享锁对象。


睡眠/中断和等待/通知之间的一个潜在的巨大差异是

在不需要时生成异常是低效的。 如果你的线程以较高的速度进行通信,那么如果你一直在调用中断,那么就会产生很多异常,这完全是CPU的浪费。


简而言之,等待是等待直到某个其他线程调用你,而睡眠是“不执行下一个语句”一段指定的时间。

此外sleep是Thread类中的静态方法,它在线程上运行,而wait()在Object类中并在对象上调用。

还有一点,当您在某个对象上调用wait时,涉及的线程会同步该对象,然后等待。 :)


还没有提到的一个关键区别是,在休眠时,线程不会释放它所持有的锁,而在等待释放时,会调用wait()对象上的锁。

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

这是一个非常简单的问题,因为这两种方法的用法完全不同。

主要区别在于等待释放锁或监视器,而睡眠在等待期间不释放任何锁或监视器。 等待用于线程间通信,而睡眠用于暂停执行。

这只是一个清楚而基本的解释,如果你想要更多,那么继续阅读。

wait()方法的情况下,线程进入等待状态,直到我们调用notify()方法(或notifyAll()如果您有多个等待状态的线程并且想要唤醒所有的线程那些线程)。 并且您需要同步或对象锁或类锁才能访问wait()notify()notifyAll()方法。 还有一件事, wait()方法用于线程间通信,因为如果线程处于等待状态,则需要另一个线程来唤醒该线程。

但是在sleep()情况下,这是一种用于保持过程几秒钟或所需时间的方法。 因为您不需要激发任何notify()notifyAll()方法来恢复该线程。 或者你不需要任何其他线程回调该线程。 就像如果你希望在用户回合后的几秒钟之后想要发生什么事情,你希望用户等待直到电脑播放,那么你可以提到sleep()方法。

还有一个更重要的区别是在访谈中经常被问到: sleep()属于Thread类, wait()属于Object类。

这些都是sleep()wait()之间的区别。

两种方法之间有相似之处:它们都是checked语句,因此您需要尝试catch或throws来访问这些方法。

我希望这能帮到您。


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

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

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

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

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

它们可以在底层操作系统中以相同的方式实现,或根本不实现(因为以前的Java版本没有真正的多线程;可能有些小型的虚拟机也不这样做)。 不要忘记Java在虚拟机上运行,​​所以你的代码会根据运行的虚拟机/操作系统/硬件而变化。





java-threads