本文主要是介绍终于明白阿里百度为什么拿WaitNotify通知机制考察求职者了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
作为一名java程序员,相信都知道wait/notify的通知机制可以用来实现线程间通信。
求职面试时,不少公司都会出类似这样的题目。笔者有次面试时,面试官就问了这样一个问题:
wait/notify/notifyAll一般适用于什么场景?
由于笔者之前对这个知识点没有重视,面试官调侃说,你对WaitNotify通知机制都没有掌握,难怪你期望薪资那么低。
我们知道,wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或notifyAll方法才可另其继续执行。经典的生产者、消费者模式即是使用wait/notify机制得以完成。
在了解wait/notify通知机制前,我们先回顾下java线程的生命周期。
今天我们针对此知识点,来编写个例子加深理解。
假设我开了一家水果实体店,日常经营主要有两项,一项是进货,一项是卖货。需要满足如下条件:
往店里进货,前提是店里库存不足,如果库存充足,则无需进货,直到把货卖出去了。
卖货,前提店里库存充足,库存不足时就要进货。
新建个水果店抽象类AbstractFruitStore
1public interface AbstractFruitStore {
2 void consumer(int num);
3
4 void producer(int num);
5}
水果实体店类实现AbstractFruitStore
1/**2 * 水果店3 */4public class FruitStore implements AbstractFruitStore {5 private final int MAX_SIZE = 100;6 private LinkedList list = new LinkedList();78 @Override9 public void consumer(int num) {
10 synchronized (list) {
11 //条件不满足,进入等待状态
12 while (num > list.size()) {
13 System.out.println("【要消费】:" + num + "\t【现库存量】:" + list.size() + "\t库存不足,暂不支持消费");
14 try {
15 //条件不满足,生产阻塞
16 list.wait();
17 } catch (InterruptedException e) {
18 e.printStackTrace();
19 }
20 }
21 //条件满足,开始消费
22 for (int i = 0; i < num; i++) {
23 list.remove();
24 }
25 System.out.println("【已消费】:" + num + "\t【现库存量】:" + list.size());
26 list.notifyAll();
27 }
28}
29
30@Override
31public void producer(int num) {
32 synchronized (list) {
33 while (list.size() + num > MAX_SIZE) {
34 System.out.println("【要生产】:" + num + "\t【库存已有】:" + list.size() + "\t库存充足,暂不支持生产");
35 try {
36 //条件不满足,生产阻塞
37 list.wait();
38 } catch (InterruptedException e) {
39 e.printStackTrace();
40 }
41 }
42 for (int i = 0; i < num; i++) {
43 list.add(new Object());
44 }
45 System.out.println("【已生产】:" + num + "\t【现库存量】:" + list.size());
46 list.notifyAll();
47 }
48 }
49}
生产者Producer
1 /**2 * 生产者3 */4public class Producer extends Thread {5 private int num;6 public AbstractFruitStore abstractFruitStore;78 public Producer(AbstractFruitStore abstractFruitStore) {9 this.abstractFruitStore = abstractFruitStore;
10 }
11
12 public void setNum(int num) {
13 this.num = num;
14 }
15
16 @Override
17 public void run() {
18 producer(num);
19 }
20
21 public void producer(int num) {
22 abstractFruitStore.producer(num);
23 }
24}
消费者Consumer
1/**2 * 消费者3 */4public class Consumer extends Thread {56 private int num;78 private AbstractFruitStore abstractFruitStore;9
10 public Consumer(AbstractFruitStore abstractFruitStore) {
11 this.abstractFruitStore = abstractFruitStore;
12 }
13
14 public void run() {
15 consumer(num);
16 }
17
18 public void consumer(int num) {
19 abstractFruitStore.consumer(num);
20 }
21
22 public void setNum(int num) {
23 this.num = num;
24 }
25}
1public class WaitNotifyTest {2 public static void main(String[] args) {3 AbstractFruitStore abstractFruitStore = new FruitStore();4 //消费者对象5 Consumer c1 = new Consumer(abstractFruitStore);6 Consumer c2 = new Consumer(abstractFruitStore);7 Consumer c3 = new Consumer(abstractFruitStore);89 c1.setNum(10);
10 c2.setNum(20);
11 c3.setNum(30);
12
13 // 生产者对象
14 Producer p1 = new Producer(abstractFruitStore);
15 Producer p2 = new Producer(abstractFruitStore);
16 Producer p3 = new Producer(abstractFruitStore);
17 Producer p4 = new Producer(abstractFruitStore);
18
19 p1.setNum(20);
20 p2.setNum(30);
21 p3.setNum(50);
22 p4.setNum(80);
23
24 //启动消费者线程
25 c1.start();
26 c2.start();
27 c3.start();
28 //启动生产者线程
29 p1.start();
30 p2.start();
31 p3.start();
32 p4.start();
33 }
34}
运行结果:
从中我们可以得出,Wait-Notify场景一般和下面3个因素相关:
状态变量(State Variable)
当线程需要wait时,是因为一些条件得不到满足导致的。例如往队列里填充数据,当队列元素已经满时,线程就需要wait停止运行。当队列元素有空缺时,再继续自己的执行。条件断言(Condition Predicate)
当线程确定是否进入wait或者是从notify醒来的时候是否继续往下执行,大部分都要测试状态条件是否满足。条件队列(Condition Queue)
每个对象都有一个内置的条件队列,当一个线程在该对象锁上调用wait函数的时候,就会将该线程加入到该对象的条件队列中。
总结
如果线程调用了Object对象的wait()方法,那么线程会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
当有线程调用了Object对象的notify()方法(只随机唤醒一个wait线程)或是notifyAll()方法(唤醒所有wait线程)被唤醒的的线程会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,只有线程再次调用wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了synchronized代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
一个知识点不仅能考验求职者的对该知识点的掌握程度,还延伸出其他知识点,考验求职者的知识面,难怪阿里百度这样的大公司喜欢在面试时拿它来考验求职者。
由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,请大家批评指正。
-END-
作者:洪生鹏 擅长java、Android、qt、小程序平台开发。技术交流、媒体合作、品牌宣传请添加微信: hsp-88ios
猜你喜欢
养成了定期更新简历的习惯,我不再像以前那么焦虑了
更多惊喜,请长按二维码识别关注
你若喜欢,别忘了帮忙点【在看】
这篇关于终于明白阿里百度为什么拿WaitNotify通知机制考察求职者了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!