lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

转载:https://www.cnblogs.com/itdragon/p/9026994.html

大家好,我是ITDragon龙,今天分享一些面试中常问的题目,和一些面试感受。我是四月二十五号离职,二十六号上午八点从深圳出发,下午三点到武汉。二十七号便开始参加面试。每天的节奏基本是:上午去公司面试,中午去小区房子装修监工,下午再去公司面试,中途还有几个电话面试,晚上再把印象深刻的面试题弄清楚。回来的这几天痩了几斤肉!这几天的面试给我很多感受。

一、面试的几家公司大部分是北上广深在武汉建立的研发部门。原因很简单,武汉人才性价比高。

二、面试的几家公司大部分面试官都会很直接告诉你加班强度很大。

三、无关技术,从深圳回到武汉,工资大概要打七折。原因嘛,五花八门。

四、灰常的堵,特别是光谷软件园,电动车都不看红绿灯,各种瞎闯。

因为房子和交通,我选择公司的范围缩小了很多。因为回来匆忙,对于面试题和公司都没有很好的了解,因此在面试中一直处于劣势。现在把自己的面试经验分享出来,帮大家把部分坑填平。预祝大家都能拿高薪。我这炮灰的作用也算是尽职了。

找工作不将就

找工作不能将就,不能进公司后发现不满意而选择离职,这样对自己和对公司都有损失。所以一开始就要问清楚。以下是我比较在意的四个点,仅供参考。

一、加班强度:现在程序员加班已成常态,产品发布还要等到夜深人静的时候。我觉得程序员就像一支蜡烛,燃烧自己照亮世界。加班一定要适量。不加,老板不会放过你!多加,医生也不会放过你!所以我希望加班强度不能太大。

二、出差频率:有的人喜欢出差,有的人不喜欢出差,比如我。

三、额外待遇:比如每月的绩效奖金,项目现金,一年的年终奖。年终奖一定要问清楚:未满一年的是怎么计算?发的是基本工资?除了每月固定工资外,一定要有其他额外福利,不然动力从何而来。

四、接触领域:如果有机会进入贵公司,最好问清楚接触的技术领域,最好是主流的技术。不建议推倒车。

你需要清楚一点:你用一个月加班换来的钱,还不够在医院消费一次

技术面试题

你需要清楚一点:回答技术问题的时候,面试官希望听到更多的答案

IO和NIO的区别

这是一个很常见的问题,如果单纯的只回答IO和NIO的区别,只能算及格。我个人觉得应该从以下几个方面回答:

1)、IO简介,

2)、TCP的三次握手,因为这也是两者的区别之一,

3)、NIO简介,

IO:(Block-IO)是一种阻塞同步的通信模式。是一个比较传统的通信方式,模式简单使用简单。但并发处理能力低(每次连接都会创建新的线程进行链路处理),通信耗时(TCP三次握手),依赖网速

TCP三次握手

第一次握手:建立连接,客户端发送syn包到服务器端,等待服务器确认

第二次握手:服务器收到客户端传来的syn包,给客户端返回ack和syn包,等待客户端确认

第三次握手:客户端收到服务器传来的ack+ayn包,向服务器发送ack包,连接建立成功

NIO:(New IO / Non-Block IO)是一种非阻塞同步的通信模式。客户端和服务器之间通过Channel通信(避免TCP建立连接使用三次握手带来的开销)。NIO在Channel进行读写操作。这些Channel都会被注册在Selector多路复用器上。Selector通过一个线程不停的轮询这些Channel。找出已经准备就绪的Channel执行IO操作。

参考文档

IO,BIO,AIO区别

TCP三次握手详细介绍

Java堆和栈的区别

1)、堆和栈的共同点,

2)、堆和栈的区别,

3)、线程之间数据共享,

Java内存分两类,一类是堆内存,一类是栈内存

堆:主要用于存储实例化的对象,数组。由JVM动态分配内存空间。一个JVM只有一个堆内存,线程是可以共享数据的。

栈:主要用于存储局部变量和对象的引用变量,每个线程都会有一个独立的栈空间,所以线程之间是不共享数据的。

既然回答了内存,其实可以把内存溢出的情况一并回答。

谈谈内存溢出

1)、先回答什么是内存溢出,

2)、再谈谈内存溢出的原因,

3)、最后提出几个内存溢出的解决方案,

内存溢出:程序运行实际使用的内存大于虚拟机设置的内存

溢出原因:

1)、虚拟机配置参数设置不合理

2)、代码中出现死循环或者产生大量的重复对象实体

3)、数据流如果没有闭关也容易导致

4)、内存中一次性加载的数据量过于庞大

5)、大量的垃圾不能被JVM回收

解决方案:

1)、最直接,最不负责的方案就是修改JVM启动参数

2)、正确流程是通过检查错误日志,查找OutOfMemory错误原因,然后修改bug

JVM垃圾回收机制

1)、先回答什么是JVM认为的垃圾,

2)、都有那些常用的垃圾回收算法,

3)、都有那些常用的垃圾回收器,

JVM认为那些不被使用的对象就是垃圾,需要从内存中除掉。

常用的垃圾回收算法有:引用计算法,标记清除法,标记压缩法,复制算法,分代,分区思想

引用计算法:古老的算法,对象被引用时加一,引用断开时减一,若为零则被当成垃圾回收。频繁加减操作性能低。

标记清除法:先把垃圾"标记"(遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象),后统一"清理"。清理后的内存空间不连续,性能不高。

标记压缩法:在标记清除法的基础上做一个压缩功能。

复制算法:内存被分为两个大小相同的A,B两块,使用A内存时,将把A内存中的活对象复制到B,然后清空内存A中的所有对象。使用B内存也是一样的。缺点是内存变小了。

分代思想:新生代,老年代(新生代中的对象经过频繁的GC中存活下来的对象)。新生代因为存活率低,需要复制的对象少,建议用复制算法。老年代存活率高,需要清理的对象少,建议用标记压缩法。

分区思想:将整个内存分为多个独立空间。在每个独立空间进行垃圾回收,提高系统性能。

串行垃圾回收器:使用单线程进行垃圾回收

并行垃圾回收器:使用多线程进行垃圾回收,对性能要求比较高

CMS收回器:并发回收器,比并行更快,当占用的资源更多,可以尽可能减少系统停顿时间

G1回收器:JDK1.7之后提供的新的收集器,是基于标记压缩的算法,特点是针对整个java堆进行

参考文档:

JVM系列博客:https://blog.csdn.net/column/details/javavirtualmachine.html

lock和synchronized区别

1)、简单介绍两者的区别

2)、工作中建议使用synchronized的原因

3)、JDK1.6之后对synchronized的优化

synchronized:关键字,在jvm层面上,线程正常执行完后会释放锁,若线程发生异常则由jvm释放锁,jdk1.5之前没有锁竞争机制,容易出现线程一直阻塞的情况,只适合少并发量使用。
Lock:类,必须在finally中释放锁,因为添加了锁竞争机制,不会出现线程一直等待的问题,适合高并发量使用。

工作中建议使用synchronized关键字,原因很简单,jdk1.6之后对synchronized做了大量的优化。为了减少获得锁和释放锁所带来的性能消耗,引入了“轻量级锁”和“偏向锁”来提高性能。

一、适应性自旋

降低了线程在等待锁的过程中的开销。因为线程从挂起到恢复是很耗时的,有些线程在挂起后很短的时间内就可以获取锁,通过漫无目的的循环让线程暂不挂起。适应性自旋表现在自选的循环次数是根据实际情况来定。

二、锁消除

删除一些没必要的加锁操作。

三、锁粗化

虽然减小锁的粒度,可以提高性能。但有些代码明明只需要加一把锁,你非要加多个??锁粗化可以把多次加锁和解锁合并成一次,用以提高效率。

四、轻量级锁

轻量级锁所适应的场景是线程交替执行同步块的情况,如果存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁。

五、偏向锁

引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。

参考文档:

lock和synchronized区别:https://blog.csdn.net/wangtaomtk/article/details/52264043

lock和synchronized区别:https://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1

HashMap底层实现

1)、简单谈谈HashMap的底层实现

2)、HashMap和HashTable的区别

3)、工作中线程安全的HashMap使用

HashMap的底层是链表散列的数据结构,即数组和链表的结构。通过计算key的hash值确定数组的位置,若该位置已经有值,则往该元素后面添加,形成一个链表。每个Entity存储hash,key,value,next四个值。在检索中,通过hash找到数组的位置,然后在通过key遍历链表,直到找到为止。在jdk1.8以后,若链表长度超过阙值后,会将该链表转为红黑树,以提高检索效率。红黑树是自平衡查找二叉树,解决了二叉树多次插入新节点导致的不平衡。当红黑树插入新节点时会通过[变色]和[选择]来满足自身规则,详情可以参考文档连接。

HashMap,HashTable,LinkedHashMap区别

1)、HashMap不是线程安全的,HashTable是线程安全的,内部通过synchronized修改加锁,其性能较差

2)、HashMap允许一个key为null,HashTable不允许

3)、HashMap的初始容量是16,而HashTable的初始容量是11

4)、工作中HashMap的使用频率较高,若希望值有序则使用LinkedHashMap,若考虑线程安全则使用ConcurrentHashMap,ConcurrentHashMap使用分段式锁性能比HashTable好。

参考文档:

ArrayList和LinkedList的区别,Java 常用List集合使用场景分析

HashMap的实现原理:https://blog.csdn.net/tuke_tuke/article/details/51588156

hashMap和hashTable的区别:https://www.cnblogs.com/aspirant/p/6856487.html

什么是红黑树:http://www.sohu.com/a/201923614_466939

Java单例模式实现

1)、什么是单例模式

2)、常见的单例模式有那些

3)、写出其中的一种

单例模式:某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

常见的单例模式有:懒汉模式,饿汉模式,静态类内部加载

// 线程安全的静态类内部加载
public class SingletonDemo{
    private static class SingletonHolder{
        private static SingletonDemo instance = new SingletonDemo();
    }
    public static SingletonDemo getInstance() {
        return SingletonHolder.instance;
    }
}

参考文档:

https://www.cnblogs.com/cielosun/p/6582333.html

谈谈MVC模式

听到这个问题时,我是窃喜的,多么简单的问题,可是面试的时候,却不知道该怎么回答。

MVC:model,view,controller。

Model:模型层,负责实现业务逻辑,操作数据库

View:视图层,负责页面展示

Controller:控制层,负责处理请求

我们通过实际的框架来了解,

SpringMVC,它实现了mvc设计模式的web框架。用户发送的请求会通过前端控制器(DispatcherServlet),根据URL映射到对应的Handler中。而这个Handler可以是用注解@RequestMapping修饰的方法,而这个方法所在的类可以用注解Controller修饰表明该类是一个控制层。可以在方法里面调用接口完成业务逻辑的操作和数据修改,将返回的结果放在ModelAndView变量中。DispatcherServlet会通过视图解析器拼接返回页面的路径,并将数据放到作用域中,渲染给用户。实现业务逻辑的接口可以理解为Model层,处理请求的类可以理解为Controller层,页面就是View层。

谈到SpringMVC,就不会少了Struts2,

Struts2也是一个基于MVC设计模式的Web应用框架,在web.xml文件中将符合要求的请求交给Servlet处理,这个 Servlet再参考struts-config.xml文件找到对应的action方法,执行完成后关联到对应的页面。SpringMVC比Struts2简单了很多。

我们再简单谈谈Hibernate,Mybatis,SpringData

我们还可以再谈谈Spring

还有设计原理

偏应用的问题

因为时间和精力的情况,这里只做简单整理的问题。

一、redis事务是怎么做的?

答:redis的事务主要是通过multi(开启事务),exec(提交事务),watch(监控版本号)几个命令完成的。

二、如何实现抢购防超卖功能?

答:抢购,秒杀的场景下既要保证用户体验, 又要防超卖。其实很简单,减少数据库的调用,1000个商品限时抢购,就是1000个数字减一。通过加锁保证线程安全。使用缓存提高效率。

三、如何设计数据查询接口保证数据的安全和性能?

答:安全:服务器接口令牌验证;查询参数长度校验;查询参数格式校验(避免sql注入);

性能:索引优化;Ehcache本地缓存;redis缓存预热;

四、Nginx如何做权限拦截?

答:Nginx和lua可以实现权限拦截

五、2*16如何最快计算结果?

答:向左移动4位

六、架构如何用一个字段设置10个Boolean型权限?

答:用int型字段,分别用0,1表示false和true

七:为什么不用mysql做分布式锁?

答:我会从性能方面回答,用redis做分布式锁,是判断key值是否存在,存在则表示有锁。用Zookeeper做分布式锁,是判断临时节点是否存在,存在则表示有锁。而mysql做分布式锁在并发量高的情况下出现死锁。

八:分布式系统如何避免消息重复消费?

答:从生产者避免重复发送角度:将生产者发送的消息持久化到数据库中,如有相同的信息则不再保存;当生存者服务的事务完成后,消息服务会将数据库中的消息发送给消费者。
从消费者避免重复消费角度:消费者服务可能是集群,要考虑幂等性。查询和删除是天然的幂操作,所以我们要在更新和创建之前做判断,是否已经存在,是否已经更新。

九、你对我们公司的了解么?
答:.......

先暂时到这里,喜欢的朋友可以关注我,觉得这篇文章对你有帮助也可以点赞,如有问题,请尽快联系我,会及时修改。

posted on 2019-04-20 20:00  白露~  阅读(844)  评论(0编辑  收藏  举报