首先sleep是Thread类中的静态方法,而wait是Object类里的被final修饰的方法。
其次,当我们使用sleep()时,只能在指定的时间内让线程进行“休眠”,规定的时间一过,线程会自动恢复运行状态,而当wait()不设置时间时,会让线程进入等待池等待,直到另一个对象调用调用该对象的notify()方法或者notifyAll()方法,该线程才会恢复到运行状态;若wait()设置了时间则规定时间一过也会自动回到运行状态。
最后,sleep()和wait()执行时都会释放cpu的执行权,但是sleep()执行时不会主动释放锁,而wait()会主动释放锁。
怎么理解后面两点呢,我们举一个例子:
public class wait和sleep {
public static void main(String[] args) {
M1 m1 = new M1();
M2 m2 = new M2();
Thread thread = new Thread(m1);
Thread thread1 = new Thread(m2);
thread1.start(); //我们先执行进行了wait()的线程
try {
Thread.sleep(500);//等待0.5s
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
thread.start(); //再执行进行sleep()的线程
}
}
class M1 implements Runnable {
@Override
public void run() {
System.out.println("M1---sleep");
synchronized ("A") {
"A".notify(); // 唤醒正在等待的thread1线程
try {
Thread.sleep(1000); // 让该线程睡眠
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("M1---sleep--over");
}
}
}
class M2 implements Runnable {
@Override
public void run() {
System.out.println("M2---wait");
synchronized ("A") {
try {
"A".wait(); // 让该线程进入等待池
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("M2---wait--over");
}
}
}
这里我们把M1和M2使用同一把对象锁锁起来,用来查看wait()和sleep()操作对对象锁的处理。我们首先执行的是启动M2对象的线程,若wait()不会释放锁的话,我们的另一个线程也会因为对象锁而无法执行。反之。
结果:
这时程序是顺利执行完毕的。
我们若要把 “A”.notify();删除,则结果为:
控制台的红色正方形表示程序还在运行,因为我们删除了"A".notify();所以M2程序一直在等待状态,没有结束。