wait和sleep方法的区别

参考:https://www.cnblogs.com/loren-Yang/p/7538482.html

 paragraph…
  paragraph…

两者的区别

1)来自不同的类:

sleep()方法是Thread类中的一个静态方法;

wait()属于Object类的成员方法。

(2)唤醒条件不同:

  Sleep()方法属于Thread类中方法,表示让当前线程进入睡眠状态,等待一定的时间后,便会自动醒来进入可运行状态;

  一旦某个线程对象调用了wait()方法,就必须要在其他线程中使用notify()或notifyAll()方法才能唤醒它。

(3)异常捕获不同:

  在sleep的过程中有可能被其他对象调用它的interrupt()方法,产生InterruptedException异常,所以要使用sleep方法必须对其捕获异常;

  而使用wait(),notify()和notifyAll()方法不需要进行捕获异常 。

(4)最主要区别是对带锁Synchronized资源的控制权:

  Sleep()方法没有释放锁。一个线程对象调用了sleep()方法之后,并不会释放它所持有的所有对象锁;

  Wait()方法释放了锁。使得其他线程可以有机会使用带锁代码块或者带锁方法。
  
PS:
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。
  • 也就是说,调用了notify后只会有一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

补充两个重要的方法: yield()和join()

  yield方法暂停当前正在执行的线程对象。
  yield()方法是停止当前线程,让同等优先权的线程或更高优先级的线程有执行的机会。如果没有的话,那么yield()方法将不会起作用,并且由可执行状态后马上又被执行。

  join方法是用于在某一个线程的执行过程中调用另一个线程执行,等到被调用的线程执行结束后,再继续执行当前线程。

如:

1
2
t.join(); 
//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

说一下为什么使用wait()方法时,一般是需要while循环而不是if?

1
2
3
4
5
6
7
8
9
while(!执行条件) {
wait();
}
....

if(!执行条件) {
wait();
}
....

  while会一直执行循环,直到条件满足,执行条件才会继续往下执行。if只会执行一次判断条件,不满足就会等待。这样就会出现问题。

  我们知道用notify() 和notifyAll()可以唤醒线程,一般我们常用的是notifyAll(),因为notify(),只会随机唤醒一个睡眠线程,并不一定是我们想要唤醒的线程。如果使用的是notifyAll(),唤醒所有的线程,那你怎么知道他想唤醒的是某个正在等待的wait()线程呢,如果用while()方法,就会再次判断条件是不是成立,满足执行条件了,就会接着执行,而if会直接唤醒wait()方法,继续往下执行,根本不管这个notifyAll()是不是想唤醒的是自己还是别人,可能此时if的条件根本没成立。

举个例子:
  while去水果店买苹果,没有了,然后while就和水果店老板说,有水果的时候通知我,我先回去了。if也去水果店买苹果,没有了,然后if就和水果店老板说,有水果的时候通知我,我先回去了。过一段时间,水果店老板发短信告诉while和if,有水果了,while去一看,水果店只是进了香蕉,并不是苹果,所以不是想要的水果,于是回去继续等水果店老板通知,而if根本就不看是不是自己想要的苹果,直接就叫老板送10斤水果过来,这样会导致你得到错误的结果。
  
参考文献:
Java中wait 和sleep 方法比较
JAVA-sleep()和wait()的区别
java中的sleep()和wait()的区别

 

---------------- The End ----------------
0%