线程状态图
开局先奉上这张线程状态图,个人觉得画的不错
几点结论
- 使用 wait ,notify 和 notifyAll 时需要先对调用对象加锁。
- 调用 wait 方法后,线程状态有 Running 变为 Waiting,并将当前线程放置到对象的 等待队列。
- notify 或者 notifyAll 方法调用后, 等待线程依旧不会从 wait 返回,需要调用 noitfy 的线程释放锁之后,等待线程才有机会从 wait 返回。
- notify 方法将等待队列的一个等待线程从等待队列种移到同步队列中,而 notifyAll 方法则是将等待队列种所有的线程全部移到同步队列,被移动的线程状态由 Waiting 变为 Blocked。
- 从 wait 方法返回的前提是获得了调用对象的锁。
wait 和 notify 例子
import java.util.concurrent.TimeUnit;
public class WaitNotify {
final static Object lock = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程 A 等待拿锁");
synchronized (lock) {
try {
System.out.println("线程 A 拿到锁了");
TimeUnit.SECONDS.sleep(1);
System.out.println("线程 A 开始等待并放弃锁");
lock.wait();
System.out.println("线程 A 被通知可以继续执行 则 继续运行至结束");
} catch (InterruptedException e) {
}
}
}
}, "线程 A").start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程 B 等待锁");
synchronized (lock) {
System.out.println("线程 B 拿到锁了");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
}
lock.notify();
System.out.println("线程 B 随机通知 Lock 对象的某个线程");
}
}
}, "线程 B").start();
}
}
运行结果如下:
线程 A 等待拿锁
线程 A 拿到锁了
线程 B 等待锁
线程 A 开始等待并放弃锁
线程 B 拿到锁了
线程 B 随机通知 Lock 对象的某个线程
线程 A 被通知可以继续执行 则 继续运行至结束
关于wait()和sleep()
这两个方法都可以让线程等待,但是wait()方法可以被唤醒。还有一个重要的区别是wait()会释放目标对象锁,而sleep()不会释放任何资源。
- wait和sleep方法都可以使线程进人阻塞状态。
- wait和sleep方法均是可中断方法,被中断后都会收到中断异常。
- wait是Object的方法,而sleep是Thread特有的方法。
- wait方法的执行必须在同步方法中进行,而sleep则不需要。
- 线程在同步方法中执行sleep方法时,并不会释放monitor的锁,而wait方法则会释放monitor的锁。
- sleep方法短暂休眠之后会主动退出阻塞,而wait方法(没有指定wait时间)则需要被其他线程中断后才能退出阻塞。
2020年09月09日 10:47:14
测试评论