我们知道wait和sleep方法可以将一个线程阻塞的目的。wait是将线程从Running变为waiting,直到被notify或者notifyAll,才会将线程从waiting状态变成Runnable状态。sleep是在一段时间内将线程从Running变为waiting,时间过去之后,线程进入Runnable状态。
在状态转换的时候,锁资源发生什么变化呢?
首先我们用一个demo来进行分析:
用于测试 wait 的 WaitTest.java |
public class WaitTest {
public void test(Object obj){
synchronized (obj){
try {
System.out.println("wait begin!");
obj.wait();
System.out.println("wait end!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
用于测试 notify 的 NotifyTest.java |
public class NotifyTest {
public void test(Object obj){
synchronized (obj){
System.out.println("notify begin");
obj.notify();
System.out.println("notify end");
}
}
}
用于测试 sleep 的 SleepTest.java |
public class SleepTest {
public void test(Object obj){
synchronized (obj){
try {
System.out.println("sleep begin!");
Thread.sleep(1000);
System.out.println("sleep end!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
用于对比测试的 CliTest.java |
public class CliTest {
public static void main(String[] args) {
Object lock = new Object();
new Thread(()->{
new WaitTest().test(lock);
},"Wait").start();
new Thread(()->{
new NotifyTest().test(lock);
},"Notify").start();
new Thread(()->{
new SleepTest().test(lock);
},"Sleep").start();
}
}
demo测试结果 |
我们可以根据测试结果可以知道:
1,wait方法调用了之后,线程立马放弃了CPU资源,并没有执行 “wait end !”
2,接着调用了notify方法,但是notify方法并没有停下来,而是继续打印了 ”notify end “,说明notify并没有放弃CPU资源。
3,之前被wait的线程,刚刚notify给唤醒了,继续执行没有执行完的部分
4,sleep方法调用时,可以看到线程明显有被阻塞。但是设定一过,就自己开始继续执行。可以说明sleep方法会让线程阻塞,但是并没有放弃自己所持有的锁,阻塞完毕后,它任然持有锁,可以接着执行之前阻塞之后的任务。