做零售去哪个外贸网站,google安卓手机下载,电子商务网站建设的体会,网站开发的步骤实训内容由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知。但是实际开发中有时候我们可以通过一些 api 让线程主动阻塞#xff0c;从而控制多个线程之间的执行先后顺序.
完成这些操作就需要用到 wait#xff0c;notify / notifyAll
注意: wait, notify, notifyAll…由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知。但是实际开发中有时候我们可以通过一些 api 让线程主动阻塞从而控制多个线程之间的执行先后顺序.
完成这些操作就需要用到 waitnotify / notifyAll
注意: wait, notify, notifyAll 都是 Object 类的方法. wait()方法
某个线程调用 wait 方法就会进入阻塞无论是通过哪个对象 wait 的此时就处在 WAITING
wait 做的事情
1. 释放当前的锁
2. 进行阻塞等待
3. 收到通知后, 重新尝试获取这个锁. 因此 wait 要搭配 synchronized 来使用. 脱离 synchronized 使用 wait 会直接抛出异常没锁怎么解锁。
public class ThreadDemo16 {public static void main(String[] args) throws InterruptedException {Object object new Object();synchronized (object) {System.out.println(wait 之前);object.wait();System.out.println(wait 之后);}}
} 这样在执行到object.wait()之后就一直等待下去但程序肯定不能一直这么等待下去。这个时候就需要使用到了另外一个方法唤醒了notify()。
notify()方法
notify 方法是唤醒等待的线程
public class ThreadDemo17 {public static void main(String[] args) throws InterruptedException {Object object new Object();Thread t1 new Thread(() - {// 这个线程负责进行等待System.out.println(t1: wait 之前);try {synchronized (object) {object.wait();}} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t1: wait 之后);});Thread t2 new Thread(() - {System.out.println(t2: notify 之前);synchronized (object) {// notify 务必要获取到锁, 才能进行通知try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}object.notify();}System.out.println(t2: notify 之后);});t1.start();// 此处写的 sleep 500 是大概率会让当前的 t1 先执行 wait 的.// 极端情况下 (电脑特别卡的时候), 可能线程的调度时间就超过了 500 ms// 还是可能 t2 先执行 notify.Thread.sleep(500);t2.start();}
} 如果 t2 不进行 notify 此时 t1就会一直等。因此 wait 也提供了一个带参数的版本可以指定最大等待时间。 这个带有等待时间的版本和 sleep 有点像。他们都能指定等待时间也都能被提前唤醒 wait 是使用 notify 唤醒sleep 是使用 interrupt 唤醒但这里的含义却截然不同。notify 唤醒 wait 不会有任何异常interrupt 唤醒 sleep 则是出异常了。 如果有多个线程等待 object 对象此时只有一个线程 object.notify()会随机唤醒一个等待的线程不知道具体哪个。但是可以用多组不同的对象来唤醒指定的线程。 在notify()方法后当前线程不会马上释放该对象锁要等到执行notify()方法的线程将程序执行完也就是退出同步代码块之后才会释放对象锁。
public class ThreadDemo18 {// 有三个线程, 分别只能打印 A, B, C. 控制三个线程固定按照 ABC 的顺序来打印.public static void main(String[] args) throws InterruptedException {Object locker1 new Object();Object locker2 new Object();Thread t1 new Thread(() - {System.out.println(A);synchronized (locker1) {locker1.notify();}});Thread t2 new Thread(() - {synchronized (locker1) {try {locker1.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(B);synchronized (locker2) {locker2.notify();}});Thread t3 new Thread(() - {synchronized (locker2) {try {locker2.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(C);});t2.start();t3.start();//这样子是为了防止 t1 先通知了t2 和 t3 就会死等Thread.sleep(100);t1.start();}
} wait 结束等待的条件
其他线程调用该对象的 notify 方法.
wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常. P 打算去 ATM 上取点钱但是这时候显示没钱了这时候 P 就要出去等在外面排队的人进去查余额、存款、转账......结果在排队的人都是取钱的这时候运钞车就来了工作人员把钱放进去之后说可以了。这时候就通知了外面的人可以取钱了先进去取的人就结束等待没进去的人只能在外面阻塞。 notifyAll()方法 和 notify 非常相似。多个线程 wait 的时候notify 是随机唤醒一个notifyAll 是所有的线程都唤醒然后这些线程再一起竞争锁。
notify 只唤醒等待队列中的一个线程. 其他线程还是乖乖等着
notifyAll 一下全都唤醒, 需要这些线程重新竞争锁 wait 和 sleep 的对比面试题
其实理论上 wait 和 sleep 完全是没有可比性的因为一个是用于线程之间的通信的一个是让线程阻塞一段时间唯一的相同点就是都可以让线程放弃执行一段时间.
当然为了面试的目的我们还是总结下
1. wait 需要搭配 synchronized 使用. sleep 不需要.
2. wait 是 Object 的方法 sleep 是 Thread 的静态方法.