wait()是Object类的方法,当一个线程执行到wait()方法时,该线程就进入到一个和该线程相关的等待池中,同时释放了对象锁(暂时失去对象锁,wait(long timeout)超时时间到后还需要返还对象锁),其他线程可以访问同步方法或同步代码块;
wait()使用notify() / notifyAll() 或者指定等待时间来唤醒当前等待的线程
wait()必须放在synchronized block中,否则会在program runtime时抛出“java.lang.IllegalMonitorStateException”异常
sleep()是Thread类的static方法,使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用,目的是不让当前线程独占该进程所获得的CPU资源,留一定的时间给其他献策换个执行的机会。
sleep()不会释放对象锁,当在一个synchronized块中使用sleep()方法时,线程虽然停滞了,但并未释放锁,其他线程无法访问这个对象。
sleep()睡眠时间期满后,改线程也不一定会立即执行,这是因为其他线程能正在运行而且没有被调度,除非该线程具有更高的优先级。
相同点:
1)两者都是在多线程的环境下,都可以在程序的调用出阻塞指定的毫秒数,并返回。
2)wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException异常。
如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt()方法。如如果此刻线程B正处在wait / sleep / join,则线程B会立即抛出InterruptedException,在catch(){ } 代码块中直接return即可安全的结束线程。
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是inerrupt()方法抛出的。对于某一线程调用interrupt()时,如果该线程正在执行普通代码,那么该线程根本就不会抛出InterruptedException异常。但是,一旦该线程进入到wait() / sleep() / join()后,就会立刻抛出InterruptedException异常。
不同点:
1)原理不同。Object类的方法:wait()、notify()、notifyAll()等, wait()用于线程间通讯,会使当前拥有该对象锁的进程等待,直到其他线程调用notify() / notifyAll()时才能醒来。
Thread类的方法:sleep()、yield()等,sleep()是线程用来控制自身流程的,会使此线程暂停执行制定时间,把执行机会让给其他线程,等到计时时间到,此线程会自动苏醒。
2)对锁的处理机制不同。wait()会释放对象锁,使得其他线程可以使用同步方法或者同步方法;sleep()不会释放对象锁。每个对象都有一个内置锁来控制同步访问,synchronized关键字可以和对象的锁交互,从而实现线程的同步。
3)使用区域不同。wait()、notify()、notifyAll()只能在同步方法或者同步代码块中使用;而sleep()方法可以在任何地方使用
4)wait()、notify()、notifyAll()不需要捕获InterruptedException异常,sleep()必须捕获异常。
由于sleep()不会释放对象锁,容易导致死锁问题的发生,所以,一般情况下,不推荐使用sleep()方法,而推荐使用wait()方法。