Board logo

标题: Thread.sleep、Object.wait、LockSupport.park 区别 [打印本页]

作者: look_w    时间: 2019-3-15 17:40     标题: Thread.sleep、Object.wait、LockSupport.park 区别

Thread.sleep() 方法

Thread.sleep(time)方法必须传入指定的时间,线程将进入休眠状态,通过jstack输出线程快照的话此时该线程的状态应该是TIMED_WAITING,表示休眠一段时间。

另外,该方法会抛出InterruptedException异常,这是受检查异常,调用者必须处理。

通过sleep方法进入休眠的线程不会释放持有的锁,因此,在持有锁的时候调用该方法需要谨慎。
Object.wait() 方法

我们都知道,java的每个对象都隐式的继承了Object类。因此每个类都有自己的wait()方法。我们通过object.wait()方法也可以让线程进入休眠。wait()有3个重载方法:

    public final void wait() throws InterruptedException;
    public final native void wait(long timeout) throws InterruptedException;
    public final native void wait(long timeout) throws InterruptedException;

如果不传timeout,wait将会进入无限制的休眠当中,直到有人唤醒他。使用wait()让线程进入休眠的话,无论有没有传入timeout参数,线程的状态都将是WAITING状态。

另外,必须获得对象上的锁后,才可以执行该对象的wait方法。否则程序会在运行时抛出IllegalMonitorStateException异常。

    Object waitObject = new Object();
    try {
        //没获取到waitObject的锁,调用该方法抛出IllegalMonitorStateException异常
          waitObject.wait();
    } catch (InterruptedException e) {
          e.printStackTrace();
    }
     
    //正确的调用方式  
    Object waitObject = new Object();
    try {
        //先获取到waitObject的锁
        synchronized (waitObject){
            waitObject.wait();
        }
    } catch (InterruptedException e) {
          e.printStackTrace();
    }

再调用wait()方法后,线程进入休眠的同时,会释放持有的该对象的锁,这样其他线程就能在这期间获取到锁了。

调用Object对象的notify()或者notifyAll()方法可以唤醒因为wait()而进入等待的线程。
LockSupport.park() 方法

通过LockSupport.park()方法,我们也可以让线程进入休眠。它的底层也是调用了Unsafe类的park方法:

    //Unsafe.java类
    //唤醒指定的线程
    public native void unpark(Thread jthread);
    //isAbsolute表示后面的时间是绝对时间还是相对时间,time表示时间,time=0表示无限阻塞下去
    public native void park(boolean isAbsolute, long time);

调用park方法时,还允许设置一个blocker对象,主要用来给监视工具和诊断工具确定线程受阻塞的原因。

调用park方法进入休眠后,线程状态为WAITING。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0