JDK官方文档定义:
Thread的sleep方法.png
Object的wait方法.png
区别可以总结为如下四点:
1. sleep方法是Thread的方法,而wait方法试试Object的方法
2. sleep不会释放对象锁,而wait方法会释放对象锁并且加入到对象锁的等待队列
定义方法m3
public static void m3() {
synchronized (LOCK) {
System.out.println(Thread.currentThread().getName() + " enter");
try {
// sleep方法不会释放锁
//Thread.sleep(10_000);
// wait方法会释放锁
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
主程序新建两个线程T1、T2运行m3方法
public static void main(String[] args) {
Stream.of("T1", "T2").forEach(name -> {
new Thread(() -> {
m3();
}, name).start();
});
}
如调用sleep方法,则在输出"T1 enter"后10秒后再输出"T2 enter",因为线程T1sleep后还会拥有Monitor,不会释放,只有当T1恢复后执行完毕释放Monitor,线程T2才会获得Monitor才会开始执行;
如调用wait方法,则在输出"T1 enter"后会立即输出"T2 enter",因为线程T1wait后会立即释放Monitor,线程T2获得Monitor,继续执行。
3. 使用sleep方法不需要监控锁(synchronized),但使用wait方法需要
先定义两个方法,m1方法调用sleep()方法,m2方法调用wait()方法
public static void m1() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void m2() {
try {
// no synchronized (LOCK) -> IllegalMonitorStateException
LOCK.wait(1000);
System.out.println("m2 end...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
分别调用方法m1、m2,
public static void main(String[] args) {
m1();
m2();
}
运行结果:m1方法运行正常,m2方法报IllegalMonitorStateException异常。
image.png
4. sleep方法不需要被唤醒,但wait方法需要
================================================================================
wait方法几点总结
1. 所有的对象都会有一个wait set,用来存放该对象wait方法之后进入block状态的线程
2. 线程被notify之后,不一定会立即执行
3. 线程从wait set被唤醒后顺序不一定是FIFO
4. 线程被唤醒后,必须重新获取锁,但是wait方法之前的代码不再执行,会接着wait方法之后继续执行
public class WaitSet {
private final static Object LOCK = new Object();
public static void main(String[] args) {
IntStream.rangeClosed(1, 10).forEach(
i -> new Thread(String.valueOf(i)) {
@Override
public void run() {
synchronized (LOCK) {
System.out.println(Thread.currentThread().getName() + "start running");
try {
Optional.of(Thread.currentThread().getName() + " will come to wait set.").ifPresent(System.out::println);
LOCK.wait();
Optional.of(Thread.currentThread().getName() + " will leave wait set.").ifPresent(System.out::println);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start());
IntStream.rangeClosed(1, 10).forEach(
i -> {
synchronized (LOCK) {
LOCK.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
执行结果:
测试.png











网友评论