3个面试中遇到的问题《JAVA面试题》

3个问题3个感悟

1. http get问题影射思维问题

与面试官的交流如下:

面试官:“一个http 请求,接受json数组,数组内容是id,返回用户信息,在测试上是ok的,到预生产就报错了,可能是什么问题?” 我想了想说:“代码一致吗?” 面试官:“当然” 我立刻说:“id中没有中文吧?” 面试官:“没有” 我略有疑虑的说:“是压力测试中,报的错吗? 如果是可能是这个借口需要加缓存提高tps了”。 面试官微微一笑说:“不是压力测试,就是单独一次调用”。 我立刻又说:“是不是后台对应的数据库挂了。造成的?” 面试官:“不是” 我再思索中,到底是什么问题呢,左思右想没有想法,正在苦恼中。 面试官略有失望的说:“你遇到bug一般如何处理呢?” 我有种瞬间被闪电击中的感觉,原来思路比答案重要 我平静的说:“定位问题,分析问题,尝试解决,重复上述步骤直到问题解决。定位问题,一般就是先看日志” 面试官略有肯定的说;“调用者的日志,显示调用的接口是500” 我进一步说:“那提供者的日志呢?” 面试官:“提示一大长串的Id,就没有其他日志了” 我细细一想说:“这个可能是测试数据少,预生产数据多,具体不是数据库的数据问题,而是传递的id多了,造成这个查询接口返回慢,可以尝试进行拆分,分批次查询” 面试官:“这个问题,先到这里,咱们换一个问题。”

看到这里,大家可能会觉得这个问题,根本不值一提,或者说记录也是没有任何意义的。但在这里我不得不说这是一个非常严重的问题,是我底层认知中的一个重要缺陷 !在信息不足的情况下,靠猜处理问题!,上边的问题如果不是面试官打断我我会一直往下猜,这种主观片面的方式如果不改,不仅面试会碰壁,生活也会走很多弯路。

**感悟1 ** 在信息不足以判断时,应先尽量通过合理有效的沟通获取更全面的信息,而不是在信息不足的情况下贸然尝试

2.半小时只能发3次消息的问题

上边的问题如果你觉得没有意思或者觉得我小题大做,没关系,下面这问题就有意思了。

面试官:“问你个算法问题吧,如何实现半小时只能发3次消息。” 我心中窃喜这个不就是限流,得意的说:“可以适用Guava的RateLimiter” 面试官略有深意的说:"不是每10分钟1次,用户可以1分钟内发3次 " 我语无伦次的说了些方案,这里经过了至少5分钟,都不对。 面试官不耐烦的说:“你刚才提到RateLimiter,它的基本实现原理是什么?” 我深吸一口气说:“令牌桶机制” 面试官略有期待的说:“如何维护令牌的?” 我战战兢兢的说;“以1s一次为例,如果没有尝试获取令牌,每秒都会更新令牌桶中的数量为1” 面试官打断我说:“你再想想这个半小时只能发3次的问题” 我心中明白这是最后一回了,如果在答不对,等待我的就是一首《凉凉》了,但是面试官问我如何维护令牌桶干什么呢?在深思10s后,我想明白了,这个问题本质还是限流,令牌桶算法还是可以解决,只是不是定时维护令牌桶中的令牌数量了,而且每次用户调用时进行维护,并且除了了令牌本身,还需要一个时间戳来协助调整令牌。 我笃定的说:"这个问题就是限流问题,还是参照令牌桶算法,但是维护机制变了。" 面试官微微一笑说;“你说说具体如何实现呢” 我淡定的说:“简单的说,系统持有一个表,表中有1个用户id,1个int类型作为剩余令牌数,1个Date类型作为上次发送时间,具体实现如下流程图”

感悟2 经典算法,活学活用,大多数业务问题均可解决。

3.线程池运行原理

面试官看了看我的简历说:“线程池用过吧” 我信心满满的说:“当然,我们项目都是使用的自扩展的线程池,我非常的熟悉” 面试官很有期待的说:“哦,那你介绍下如何扩展的吧” 我侃侃而谈:“线程池扩展,使用的是ThreadPoolExecutor,核心参数有,核心线程数,最大线程数,存活时间,存活时间的单位,队列大小,拒绝策略,拒绝策略分为4种,” 面试官:“具体说下拒绝策略” 我心想这个小意思,昂首挺胸的说:“

  • AbortPolicy默认策略 抛出未检查的异常RejectedException
  • DiscardPolicy 新任务无法保存到队列,抛弃该任务
  • DiscardOldestPolicy 新任务无法保存到队列,抛弃下一个执行的,再提交最新的
  • CallerRunsPolicy调用者执行 不抛弃任务,不抛弃异常,而将某些任务退回到 调用者。 如果队列满了,下个任务会在调用execute的主线程中执行。 有界队列和调用者执行策略,实现高负载下平缓的性能降低 ”

面试官:“概念咱们就不聊了,考虑下面这个场景,核心线程5,最大线程10,队列大小2,同时来了20个任务,使用默认的拒绝策略,任务是如何被执行的。” 我心里一下就蒙了,一般线程的队列大小至少要上千,这个队列数是2,还真没设置过。 硬着头皮,故作镇定的说:“这个最开始的5个任务会被执行,之后的2个任务会进入到队列,之后线程池新开2个线程执行队列中的任务,其他的任务都拒绝了”。 面试官:“这个问题你有点犹豫啊!” 我心里咯噔一下,哎看了是猜错了。

回家以后,我非常好奇,写了程序来校验这个问题,代码如下:

 1public class IndexBinarySearch<T> {
 2
 3
 4    public static void main(String[] args) {
 5        ThreadPoolExecutor poolExecutor=new ThreadPoolExecutor(5, 10,
 6                1,
 7                TimeUnit.MINUTES,
 8                new LinkedBlockingDeque<Runnable>(2)
 9        );
10
11        List<Runnable> rlist=new ArrayList<>();
12        for(int i=0;i<20;i++){
13            rlist.add(new RunnableTest(poolExecutor));
14        }
15        for(int i=0;i<20;i++){
16            poolExecutor.execute(rlist.get(1));
17        }
18    }
19}
20
21class RunnableTest implements Runnable{
22
23    ThreadPoolExecutor poolExecutor;
24
25    public RunnableTest(  ThreadPoolExecutor poolExecutor){
26        this.poolExecutor=poolExecutor;
27    }
28
29    @Override
30    public void run() {
31        int threadSize=this.poolExecutor.getActiveCount();
32        int queueCurrentSize=this.poolExecutor.getQueue().size();
33        System.out.println(Thread.currentThread().getName()+":执行开始:"+"当前线程数:"+threadSize+"当前队列大小:"+queueCurrentSize);
34        try {
35            Thread.sleep(1000);
36        } catch (InterruptedException e) {
37            e.printStackTrace();
38        }
39    }
40}

运行结果如下图:

从代码的运行结果上看, 前5个立即执行,后2个入队列, 之后线程池开新线程处理后边的任务,如上图紫色框部分线程6-10,直到到达最大线程数为止 之后的任务都拒绝了,如上图报错部分 等有线程执行完任务后,会从线程池中取之前的任务执行。如上图红色框部分。 总结下其大致流程图如下:

感悟3 只有了解原理,才能把一项技术应用在不同的场景下。

总结

3个问题3个感悟

  1. 在信息不足以判断时,应先尽量通过合理有效的沟通获取更全面的信息,而不是在信息不足的情况下贸然尝试
  2. 经典算法,活学活用,大多数业务问题均可解决。
  3. 只有了解原理,才能把一项技术应用在不同的场景下。

✦ ✦ ✦ ✦ ✦ ✦ ✦ ✦

作者: 温安适 原文:https://my.oschina.net/floor/blog/1841962


原文发布于微信公众号 - 架构师之旅(TravelWithFrame)

原文发表时间:2018-07-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CSDN技术头条

Hamsterdb vs. LevelDB:且看非主流数据库的自白和逆袭

【编者按】虽已问世9年之久,但是相较MongoDB,Hamsterdb的知名度仍然有所欠缺,更一度被评为非主流数据库。Hamsterdb是个开源的键值类型数据库...

2357
来自专栏温安适的blog

3个面试中遇到的问题

6月是个忙碌的月份,结完婚,处理完家事,也换了份工作。以至于6月都没有写blog,今天闲来无事,将之前面试的问题,以及一些感悟分享给大家。

1793
来自专栏涤生的博客

天池中间件大赛Golang版Service Mesh思路分享

这次天池中间件性能大赛初赛和复赛的成绩都正好是第五名,出乎意料的是作为Golang是这次比赛的“稀缺物种”,这次在前十名中我也是侥幸存活在C大佬和Java大佬的...

1714
来自专栏大数据和云计算技术

对象存储入门

10.5.3 对象接口 对象存储系统(Object-BasedStorage System)是综合了NAS和SAN的优点,同时具有SAN的高速直接访问和NAS...

8114
来自专栏Golang语言社区

Node.js真的无所不能?那些不适用的应用领域分析

Node.js是一个服务器端JavaScript解释器,底层采用的还是libevent;它的目标是帮助程序员构建高度可伸缩的应用程序,目前对Node.js 的采...

3456
来自专栏程序人生

谈谈编译和运行

[作者按] 今天 hacker news 爆炸性的新闻是我们敬爱的葛老头:Andy Grove 去了。70后,80后大多听过这个响当当的名字,也听过(或者读过)...

4079
来自专栏Rainbond开源「容器云平台」

搬运向 | 浅析serverless架构与实践

1.1K5
来自专栏CSDN技术头条

架构之路(六):把框架拉出来

【编者按】本文作者自由飞,具有 传奇般的人生经历: 98年读大学-国际贸易专业 03年11月英语培训机构当英语老师 04年2月-05年6月律师...

1929
来自专栏知识分享

关于PLC高速计数器使用

今天去面试问我高速计数器,因为没用过,所以直接说--不会.但是自己感觉自己自学电气,说不会太丢人了,所以今天学了PLC的高速计数器.虽然没有书,但是有度娘,还有...

3759
来自专栏Golang语言社区

Golang语言零基础入门资料整理

GO语言跟它名字一样是门比较装逼的语言,鲜有菜鸟初学者教程,所以没有语言基础的话,理解起来会有点困难。闲来没事整理了一个GO零基础入门资料。 安装与简介 因为国...

4456

扫码关注云+社区

领取腾讯云代金券