本帖最后由 就业高冷派 于 2018-6-23 16:57 编辑
陕西运景网络科技有限公司
公司行业:互联网/电子商务
公司规模:50-150人
公司地址:西安市高新区丈八六路与南三环辅导32号天网软件大厦 笔试题 无 面试总结: 1: 线程创建有哪些方式: Thread类和Runnable接口,Callable接口(重写call方法,有返回值, 可由FutureTask获取到)。 Callable和Future组合的应用:有一个很耗时的结果需要计算,但是又不是立即用到,就可以使用这个组合。先用Callable开启一个线程进行计算,等后边程序真正用到的时候,再由Future获取到返回值,这样用户就不用等待了。 注:面试中如果关于线程的部分忘了怎么说了,就说:使用框架之后,框架底层对线程进行了封装,所以一般也不考虑安全问题(Struts2是多例多线程,线程安全;SpringMVC是单例多线程,只要不对全局变量进行增删改,线程也是安全的)。 2: struts默认是多例多线程的,那为什么还要在controller中要使用@Scope("prototype")? struts默认是多例多线程的,线程安全;但spring创建的实例默认都是单例的,所以 struts2和spring整合之后,struts受到spring管理,变成单例的了,这样线程不安全,所以要在struts的controller中要使用@Scope("prototype")再改成多例的。 3: 说说jsp九大内置对象? page(pageContext) --> request(response) --> session --> application(最大的域) Out --> Exception --> Config(out了一个Exception,去看一下配置文件Config) 记忆:从前往后,从小往大,成对儿记忆。 1.page:page 对象代表JSP本身,只有在JSP页面内才是合法的,类似于Java编程中的 this 指针 2.pageContext:通过它可以获取 JSP页面的out、request、reponse、session、application、config等对象 3.request:封装请求参数(业务参数,请求路径,IP,端口,请求头等) 4.response:设置contentType,响应方式等 5.session:服务器为每用户都创建一个session对象,保存用户信息 6.application:服务器启动时创建,关闭时销毁。类似session,但它的生命域和声明周期比session更长,所有客户共享这个内置的Application对象(在线人员统计) 7.out:给浏览器输出信息,并管理应用服务器上的输出缓冲区 8.exception:显示异常信息,只有在包含 isErrorPage="true" 的页面才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。 9.config:获取服务器的配置信息。当一个Servlet 初始化时,容器把某些信息通过config对象传递给这个 Servlet,可以在web.xml中提供初始化参数。 4: 常见数据结构特点? A:栈 先进后出 B:队列 先进先出 C:ArrayList 查询快,增删慢 D:LinkedList 查询慢,增删快 注1: ArrayList :一般情况下,数组在内存中是连续存储的(这就是为啥创建数组时必须要指定长度,因为它要去内存中预留一块足够大的空间),通过指针去找到一个数组下标是非常快的;但是,有好就有坏,数组需要去维护下标,导致增删就比较慢。 LinkedList :链表数据存储是不连续的,比如:内存中,A空间指向B空间,B空间指向C空 间,C空间指向D空间。我要查D空间的数据,每次都要从A空间顺着找过去,跳来跳去导致查询效率很低;但是有坏就有好,链表不需要维护每个数据的地址,增删时,只需要修改该数据前后两个数据的关联地址即可。 注2: 如果数组比较大(eg: 2个G的数组),内存中可能没有那么大的连续有效空间去存储,肯定会有一些方式去打断连续存储,但跟咱们没关系。 5: 事务的特性及其意义? 4个特性:一致性,持久性,隔离性,原子性(一尺割圆) 1)一致性:不论事务成功还是失败,你的业务应该是一致的,数据不能被损坏。比如转账,你给张三转了1000,结果代码出错了,你扣了1000,但张三没有收到1000,这样数据/业务就损坏了,违反了一致性。 2)持久性:事务一旦完成,结果永久生效,无法回滚,哪怕完成的瞬间服务器挂了,它也应该把数据持久化,等服务器恢复了,它也恢复。 3)隔离性:多个事务同时处理一份数据时,事务之间应该相互隔离,否则就乱了(跟线程安全有点类似)。 4)原子性:整个方法被捆绑成一个原子,不可拆分,要么一起成功,要么一起失败(同生共死)。 l并发事务(同一时间进行的另一个事务)引起的3个安全问题(按顺序记忆): 1)脏读:A事务读取了B事务未提交的数据(一旦B事务回滚,可能会导致A事务读取的数据无效)。 2)不可重复读:一个事务方法中连续查询多次,却得到不同的结果(原因:并发事务在两次查询的瞬间对数据进行了修改)。 3)虚读/幻读:一个事务方法中连续查询多次,却得到不同的结果(原因:并发事务在两次查询的瞬间对数据进行了增加/删除)。 l数据库4个隔离级别(为了解决并发事务的安全问题): 安全性从低到高:唯一可穿 1)未提交读:安全级别最低,3个安全问题都解决不了。 2)已提交读(Oracle默认):可以解决第一个问题(脏读)。 3)可重复读(mysql默认):可以前两个问题(脏读和不可重复读)。 4)串行[又叫可序列化]:全部解决。 注意1:安全级别越来越高,那么效率就越来越低。比如串行,虽然把3个问题全解决了,但是有代价,它在执行A事务的时候,把整张表锁定了,其他事务后边排队,这样效率很低,所以基本不用。 注意2:数据库的隔离级别可以修改,但一般采用默认,不过有人为了提高mysql的性能,将其隔离级别改为第二级(已提交读),由于间隙锁的优化策略的存在,解决了不可重复读和虚读/幻读。 l事务的传播: 一个事务方法调用另一个事务方法,必须指定事务如何传播(比如:一个service方法 调用另一个service方法)。事务有7种传播行为,什么REQUIRED,REQUIRED_NEW, SUPPORTS等(随便说几个)。spring默认是Required:调用方有事务就用该事务,没有 则开启新事务。 6: 什么是死锁,并写一个死锁? 线程死锁即多个线程抢夺CPU执行权,往往由于锁的嵌套(也有其他情况),导致通信阻塞,陷入无尽等待。 数据库事务死锁 同时开启两个事务。 事务A: start transaction/begin; update t1 set age = “11” where id = 1; 事务B: start transaction/begin; update t1 set age = “22” where id = 2; 事务A继续:update t1 set age = “111” where id = 2; 发现此时阻塞,因为id=2的记录数据被事务B锁定了; 事务B继续:update t1 set age = “222” where id = 1; 此时报错: ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction 事务B回滚,事务A不再阻塞。 事务A: commit; 结果:事务A修改成功,事务B失败。 7: session和cookie的生命周期 ? session: 创建: 第一次访问jsp时,jsp会被转成servlet,在转换过程中,底层会自动调用 request.getSession()方法,去创建一个session,作为jsp九大内置对象之一和 该jsp绑定; 而访问servlet时,如果内部没有使用request.getSession()方法,是不会创建 session的;只有手动调用该方法,才会创建。 注:访问HTML,js,图片,css等静态资源是不会创建session的,因为访问 这些静态资源用不到session,跟session没有半毛钱关系,死板的创建session 和cookie 是浪费资源的。 销毁: Tomcat默认30分钟后销毁,或者手动调用invalidate()方法,使之失效。 注:服务器关闭时,如果30分钟不到,session是不会销毁的,会被持久化到 本地磁盘,服务器启动会再次加载进内存。 cookie: 创建: session创建之后,会自动创建一个cookie,把session的id存入cookie (Set-cookie:JSESSIONID=session的id),并响应给浏览器。当然,代码中可以手动new Cookie(“key”,”value”)并响应给浏览器。 销毁: 默认是浏览器关闭就销毁(cookie存储于浏览器内存,浏览器关闭,内存即释放,因而销毁),可以进行持久化,持久化之后即使浏览器关闭也不会销毁(存到硬盘上,再次打开浏览器又会被加载)。 8: 乱码问题(乱码的情况很多)? 浏览器 ---> 服务器 ---> 数据库:每个环节的数据传递都可能乱码 1.浏览器请求服务器乱码: 1)get请求乱码 浏览器向服务器使用get方式传递参数,如果有中文/日文等非字母语言时,服务器端就会产生乱码问题。因为应用程序之间的数据传递,底层都要转换成计算机能认识的二进制数据,转换过程中就涉及到编码问题。浏览器地址栏会先把参数进行utf-8编码,Tomcat 6/7接收到get请求的参数后,立即使用默认的ISO-8859-1进行解码,因而servlet/action获取的中文参数乱码。 解决方案:修改Tomcat 6/7的server.xml配置文件:URIEncoding="UTF-8", 在servlet中接收到参数后,进行逆向编码和解码:使用String的构造。 2)post请求乱码: request.setCharacterEncoding(“utf-8”); 注:使用struts2框架后,它底层自动处理了post乱码问题 3.服务器响应浏览器乱码: response.setContentType(“text/html;charset=utf-8 ”); 4.文件乱码:另存为无BOM头的UTF-8格式。 5.数据库乱码:修改数据库编码为utf-8。 注:springboot不乱码是因为内嵌的tomcat 8。 9: serialVersionUID作用? 反序列化时验证版本一致性。 序列化:将内存中的对象序列化到IO流(磁盘或网络)中。 eg:session,10万个用户并发访问时,内存可能存不下这么多session,会将一部分序列化到磁盘上(session的活化和钝化:session中的对象需要实现序列化接口,HttpSession本身是个接口,跟Serializable接口没关系)。 反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的序列化版本ID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会报异常。 file:///C:\Users\ADMINI~1.PC-\AppData\Local\Temp\ksohtml\wpsF945.tmp.jpg 注1:serialVersionUID可以不写,java编译器会根据属性名等参数会自动生成一个版本号(很长的数字串),但是如果不写,当你将对象序列化后,又将实体类属性改了,再反序列化就会报错,因为两个版本号不一致。如果你写死一个版本号,那么就算对象序列化后又对实体类进行了修改也是没关系的,属性能对应就进行序列化,新增或删除的属性就用默认值。 建议:serialVersionUID写上,因为不同版本的jdk对于其计算方式可能不同,那么进行跨虚拟机传输时可能出问题。 注2:为什么不是所有类都实现序列化接口? (String,Integer,集合等大量的类都实现了序列化接口) 安全性:序列化时私有属性是不被保护的,即通过构造方式传入的私有属性,即使不提供get/set方法,反序列化时也能获取到属性值。 资源分配问题:比如Thread,难道反序列化后CPU就能重新创建一个线程吗。
|