面试题汇总(2)

面试题汇总(2)

Q:避开多线程并发问题的解决办法

A:目前我了解到的是:1、使用不可变对象2、使用线程封闭的方法,尤其指的是ThreadLocal
不可变对象:对象创建后装态就不可以改变,对象所有的对象域都是final修饰的,对象是正确创建的(没有this逃逸)
再来复习一下final关键字,
  • final修饰类:不能被继承,例如String
  • final修饰方法:锁定方法被继承类修改,一个类的private方法会被隐式的指定为final方法。
  • final修饰变量:最常用,修饰基本数据类型的变量,初始化后数值不能够修改,修饰引用类型的变量,初始化后不能再指向另外一个对象,但是变量的值可以修改,比如hashMap。
上面说final修饰hashMap等不能保证值不被修改,Java有其他的实现方法:
  • Collections.unmodifiableXXX(map,set等),底层实现做修改就抛出异常;
  • Guava的immutableXXX(list,map,set等),底层实现类似于unmodifiableXXX;
使用线程封闭避免线程安全问题
  • 使用堆栈封闭,即使用局部变量,使用全局变量很容易出现线程安全问题
  • 使用ThreadLocal ,以线程本地对象作为key,以线程变量的副本作为value

Q:避免SQL注入的方法

A:总的来说避免SQL注入的方法有三种:
  • 使用JDBC 的prepaered statement(预编译)而不采用SQL字符串拼接的方式,这是因为预编译SQL语句会调用set方法解析SQL。典型的例子是mybatis${} 和#{}的区别美元符数据字符串拼接,井号有jdbc预编译的过程。
  • 使用字符串过滤过滤敏感词
  • 使用正则表达式过滤传入的参数
我个人认为可以在前端页面上避免SQL注入,比如写一些js代码过滤SQL语句

Q:SpringMVC、Struts1的区别

A:
  • springMVC单例非线程安全,struts1单例非线程安全,额外说一下Struts2是多例线程安全的,对每个请求都产生一个实例。
  • springMVC和Struts1的入口都是servlet,而struts2是Filter。springMVC 的前端总控制器为 DispatcherServlet,struts1 的前端总控制器为 ActionServlet,额外说一下struts2 的前端总控制器为 FilterDispatcher。
  • springMVC的拦截粒度是方法。struts的拦截粒度是类。
  • 我个人觉得挺重要的一点是springmvc用起来很方便各种注解很便利,不需要额外配置
解释一下为什么单例就是线程不安全的。类里面有静态变量和实例变量是全局的,这就存在多个线程同时访问的可能性,此时需要采用其他的同步手段,例如J.U.C的同步容器等方法。

Q:HTTP状态码

A:
200 --成功
301 --永久重定向
302 --临时重定向
404 --服务器找不到页面
405 --请求方法不匹配
500 --服务器错误
503 --服务器不能再接受请求,实际上就是服务器爆了

Q:一次完整的HTTP请求

A:
  1. 域名解析:在系统的hosts文件里查找域名对应的IP地址,没有的话向本地DNS发送一个请求报文,本地服务器必须返回完整结果,称为递归查询。如果本地DNS服务器没有,则启动一次远程查询,请求根域名服务器,每次返回一部分域名,直到找到域名对应的IP地址并返回一个响应报文,这个机制称为迭代查询。
查询报文和响应报文都作为UDP数据包发送,即DNS是基于UDP的。
DNS所有的查询***括所有的部分答案都会被缓存,缓存也是有过期时间的。
  1. 发起TCP的3次握手建立连接
  2. 建立TCP连接后发起HTTP请求
  3. 服务器响应HTTP请求,业务逻辑处理,返回HTTP响应给浏览器
  4. 浏览器得到html代码,会解析html代码,并请求html代码中的资源(如js、css、图片等,并对页面进行渲染最终呈现给用户

Q:数据库索引未命中原因是什么?如何解决?

A:
  • 函数操作:原因对条件字段做函数操作不会命中索引。
  • 隐式转换:原因可能是条件字段的类型不匹配,MySQL会做类型转换,这其中有函数操作,所以不命中索引
  • 模糊查询:原因是通配符之间的字段不命中索引,解决办法是让模糊查询包含字段开始的值。
  • 范围查询:原因是如果单次查询的数据量过大,优化器就不命中索引,解决办法是降低查询范围。
  • 计算操作:原因是对索引字段做计算操作将无法命中索引,解决办法是将计算操作放在等号后面

Q:如何优化分页查询?

A:
  • 根据自增且是连续主键排序的分页查询,方法,按照主键去查询,缩小查询范围可以命中索引。
  • 查询根据非主键字段排序的分页查询,方法,让排序时返回的字段尽可能少,具体来说就是让排序和分页操作先查出主键,然后根据主键查到对应的记录。

Q:如何优化join语句?

A:
MySQL执行关联查询的算法
  • Nested-Loop Join 算法:循环地从第一张表(称为驱动表)中读取行,在这行数据中取到关联字段,根据关联字段在另一张表(被驱动表)里取出满足条件的行,然后取出两张表的结果合集。MySQL 在关联字段有索引时,使用NLJ算法。
  • Block Nested-Loop Join 算法:把驱动表的数据读入到 join_buffer 中,然后扫描被驱动表,把被驱动表每一行取出来跟 join_buffer 中的数据做对比,如果满足 join 条件,则返回结果给客户端。MySQL 在关联字段没有索引时,使用BNLJ算法,原因是NLJ是磁盘扫描,BNLJ是内存中判断。
  • Batched Key Access 算法:将驱动表中相关列放入 join_buffer 中;批量将关联字段的值发送到 Multi-Range Read(MRR) 接口;MRR 通过接收到的值,根据其对应的主键 ID 进行排序,然后再进行数据的读取和操作;返回结果给客户端
优化关联查询
关联字段添加索引:建议在被驱动表的关联字段上添加索引,让 BNL变成 NLJ 或者 BKA ,可明显优化关联查询。
小表做驱动表:建议小表驱动大表,因为扫描的行数与驱动表的行数相关。
临时表:建议当遇到 BNL 的 join 语句,如果不方便在关联字段上添加索引,不妨尝试创建临时表,然后在临时表中的关联字段上添加索引,然后通过临时表来做关联查询

Q:如何优化数据导入?

A:
  • 一次插入多行的值; 关闭自动提交,
  • 多次插入数据的 SQL 一次提交;
  • 调整参数,innodb_flush_log_at_trx_commit 和 sync_binlog 都设置为0;












全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务