java基础面试题-看我这一篇就够了

本文汇总了Java面试中的基础题,涵盖了String、StringBuffer、StringBuilder的区别,Vector、ArrayList、LinkedList的异同,Hashtable、HashMap、TreeMap的对比,以及ConcurrentHashMap与Hashtable的比较。此外,还讲解了Tomcat、Apache、JBoss的角色,HTTP报文结构,反射机制,Hibernate的一级和二级缓存,以及Spring的IOC和AOP原理。还涉及到线程同步、JVM内存模型、SQL优化、JVM垃圾回收和线程通信等内容,是Java开发者面试准备的宝贵资料。

基础面试题精选

一、String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的?

  1. String是字符串常量,StringBuffer和StringBuilder是字符串变量。
  2. StringBuffer是线程安全的,
  3. StringBuilder是非线程安全的。
  4. 具体来说String是一个不可变的对象(String类是由final修饰的类,俗称阉割类),每次修改String对象实际上是创新新对象(补充知识点https://blog.youkuaiyun.com/MOU_IT/article/details/78312399),并将引用指向新对象。效率很低。
  5. StringBuffer是可变的,即每次修改只是针对其本身(操作同一对象,不像string可能会引用常量池中已存在的string),大部分情况下比String效率高,StringBuffer保证同步(synchronized),所以线程安全。
  6. StringBuilder没有实现同步,所以非线程安全。但效率应该比StringBuffer高(多线程操作效率要比单线程高很多)。StringBuffer使用时最好指定容量,这样会比不指定容量快30%-40%,甚至比不指定容量的StringBuilder还快。

二、VECTOR,ARRAYLIST, LINKEDLIST的区别是什么?

vector是同步的(线程同步https://www.cnblogs.com/nufangrensheng/p/3521654.html),arraylist和linkedlist不是同步的。底层方面,vector与arraylist都是基于object[]array实现的,但考虑vector线程安全,所以arraylist效率上回比vector较快(多线程操作速度优于单线程)。元素随机访问上,vector与arraylist是基本相同的 。但在插入删除数据上,linkedlist则比arraylist要快很多。linkedlist比arraylist更占内存,因为linkedlist每个节点上还要存储对前后两个节点的引用。

三、HASHTABLE, HASHMAP,TreeMap区别?

Hashmap和HashTable都实现了Map接口,但HashTable是线程安全的,HashMap是非线程安全的。
HashMap中允许key-value值均为null,但HashTable则不允许。
HashMap适合单线程,HashTable适合多线程。
HashTAble中的hash数字默认大小是11,增加方式为old*2+1,HashMap中的hash默认大小为16,且均为2的指数。
TreeMap则可以将保持的数据根据key值进行排列,可以按照指定的排序方式。默认为升序。
TreeMap线程不安全。

四、ConcurrentHashMap和HashTable的区别?

两者均应用于多线程中,但当HashTable增大到一定程度时,其性能会急剧下降(synchronization关键字,基于jvm内存计数器分配cpu占用时间)。因为迭代时会被锁很长时间。但ConcurrentHashMap(通过锁方法不会占用cpu时间,若遇到已有线程占用锁会立即释放锁)则通过引入分割来保证锁的个数不会很大。简而言之就是HashTable会锁住真个map,而ConcurrentHashMap则只需要锁住map的一个部分。

五、Tomcat,apache,jboss的区别?

Tomcat是servlet容器,用于解析jsp,servlet。是一个轻量级的高效的容器;缺点是不支持EJB,只能用于Java应用。

Apache是http服务器(web服务器),类似于IIS可以用来建立虚拟站点,编译处理静态页面。支持SSL技术,支持多个虚拟主机等功能。

Jboss是应用服务器,运行EJB的javaee应用服务器,遵循javaee规范,能够提供更多平台的支持和更多集成功能,如数据库连接,JCA等。其对servlet的支持是通过集成其他servlet容器来实现的。如tomcat。

六、GET POST区别?(总结的不够完善,想了解具体get和post请求区别的请看https://www.cnblogs.com/logsharing/p/8448446.html)
get请求方式直接将参数暴露在url中,post请求将参数放在request body。所以Post相对安全。

get是把参数数据队列加到提交表单的action属性所指的URL中,值和表单内各个字段一一对应,在url中可以看到。post是通过HTTPpost机制,将表单内各个字段与其内容放置在html header(http相关知识https://www.cnblogs.com/chenliyang/p/6558756.html)内一起传送到action属性所指的url地址。

对于get方式,服务区端用request.QueryString获取变量值,对于post方式,服务器端用request.Form获取提交的数据。get传送的数据量较小((大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。),post较大,一般不受限制。get安全性比post要低,但执行效率较高。

七、SESSION, COOKIE区别?

session数据放在服务器上,cookie则放在客户浏览器上。cookie不太安全,因为可以分析出本地cookie,并进行cookie欺骗,考虑安全应使用session。session会在一定时间内保存在服务器上,当访问增多时,会比较占用服务器的性能,考虑减轻服务器压力则应该使用cookie。单个cookie保持的数据不超过4k,很多浏览器都限制要给站点最多保存20个cookie。session创建要依赖cookie ,当一个用户登录时,服务器创建session 并在浏览器端创建一个名为SESSIONID的cookie储存sessionid,确认是否为当前登录用户。

八、Servlet的生命周期?(老铁,看这个,这个吊https://blog.youkuaiyun.com/qq_19782019/article/details/80292110)
主要分三个阶段:初始化——调用init()方法,响应客户请求阶段——调用service()方法,终止阶段——调用destroy方法。工作原理:浏览器发送一个请求,web容器(如tomcat)从硬盘中加载servlet.class文件,调用servletinit方法创建servlet实例(若不存在的情况,若存在直接用),servlet调用service()方法对请求进行响应,即对请求方式进行匹配,选择调用doGet、doPost方法等,然后进入对于的方法中调用逻辑层的方法(传递servletRequset,servletResponse实例,返回结果由servletResponse传递),实现对客户的响应。自定义的servlet必须实现servlet接口。当web容器关闭时调用distory方法销毁实例。
具体生命周期包括:装载Servlet、服务器创建Servlet实例、服务器调用Servlet的init()方法、客户请求到达服务器、服务器创建请求对象、服务创建相应对象、服务器激活Servlet的service方法,请求对象和响应对象作为service()方法的参数、service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息、service()方法可能激活其他方法以处理请求,如doGet(),doPost()

九、HTTP 报文包含内容(https://www.cnblogs.com/chenliyang/p/6558756.html)

请求方法包括GET,POST,HEAD,PUT,TRACE,OPTIONS,DELETE。请求头如:Host、User-Agent、Connection、Accept-Charset等。请求头部的最后会有一个空行,表示请求头部结束,接下来为请求正文,这一行非常重要,必不可少。请求正文为可选部分,如get就没有。
十、Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入?

使用PreparedStatement可以提升代码的可读性和可维护性,可以尽最大可能提高性能。因为Statement每次执行一个SQL命令都会对其编译,但PreparedStatement则只编译一次。PreparedStatement就类似于流水线生产。另一方面PreparedStatement可以极大提高安全性:它对传递过来的参数进行了强制参数类型转换,确保插入或查询数据时,与底层数据库格式匹配。

SQL注入:就是通过将sql命令插入到web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意SQL命令。如sql命令:select id from test where name=‘1’ or 1=1; drop table test,但用PreparedStatement就可以避免这种问题。
spring mapper文件中 #{}可以防止sql注入 ${}不能防止sql注入(https://www.cnblogs.com/soulaz/p/5587264.html)。

十一、redirect, forward区别?

redirect:服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址。所以地址栏显示是新的url。
forward : 是指服务器请求资源,直接访问目标地址url,把响应的内容读取过来并再发送给浏览器,浏览器并不知道资源从哪里来,所以地址栏不变。

redirect不能共享数据,forward转发页面和转发到页面可以共享request中的数据。redirect用于注销,forward用于登陆。forward效率高于redirect。

十二、关于JAVA内存模型,一个对象(两个属性,四个方法)实例化100次,现在内存中的存储状态,几个对象,几个属性,几个方法?

Java新建的对象都放在堆里,如果实例化100次,堆中产生100个对象,一般对象与其属性和方法属于一个整体,但如果属性和方法是静态的,则属性和方法只在内存中存一份。

十三、谈谈Hibernate的理解,一级和二级缓存的作用,在项目中Hibernate都是怎么使用缓存的?

一级缓存为session基本的缓存,是内置的不能卸载。一个Session做了一个查询操作,它会把这个结果放在一级缓存中,如果短时间内这个session又做了同一个操作,那么hibernate就直接从一级缓存中获取数据。

二级缓存是SessionFactory的缓存,分为内置缓存和外置缓存两类。即查询结果放在二级缓存中,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中获取结果。适合放在二级缓存中的数据包括:很少被修改的数据,不是很重要的数据,允许出现偶偶并发的数据,不会被并发访问的数据,参考数据。不适合放在二级缓存中的数据:经常被修改的数据,财务数据,绝对不允许出现并发,与其他应用共享的数据。

mybaits 一级缓存二级缓存

https://www.cnblogs.com/happyflyingpig/p/7739749.html

十四、反射讲一讲,主要是概念,都在哪需要反射机制,反射的性能,如何优化
能够分析类能力的程序称为反射。反射机制可以用来:在运行中分析类的能力,在运行中查看对象,如编写一个toString方法供所有类使用。实现通用的数据操作代码。利用Method对象,这个对象很像C++的指针。

反射性能优化方法主要为设置不用做安全检查。

spring ioc的核心是代理模式,代理模式基于反射机制。反射是指一个对象照镜子,看到镜子里完全一致的自己,反射可以获取对象名称,方法,字段及对象基类等。主要用户代理模式。而spring 的核心是ioc 控制反转,即主动将创建对象的任务交给spring来控制,这就少不了代理模式(不再有自己主动去new对象,而是有springAop代理创建对象)。

十五、谈谈Hibernate与Ibatis的区别,哪个性能会更高一些?

Hibernate与MyBatis都可以通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory生成Session,最后由 Session来开启执行事务和SQL语句。
而MyBatis的优势是MyBatis可以进行更为细致的SQL优化,可以减少查询字段,并且容易掌握。
Hibernate的优势是Dao层开发比MyBatis简单,
MyBatis需要维护sql和结果映射,数据库移植性,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL,有更好的二级缓存机制,可以使用第三方缓存,MyBatis本身提供的缓存机制不佳。

十六、对Spring的理解,项目中都用什么?怎么用的?对IOC、和AOP的理解及实现原理?(spring 知识点 https://www.ibm.com/developerworks/cn/java/wa-spring1/)

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
IOC 控制反转 将创建对象的任务交给spring来做。
AOP 面向切面编程,业务与业务之间是独立的,程序员只关注业务本身,事物,权限,日志,监控交由aop切面去做。AOP实现可以由有拦截器和过滤器实现。

十七、线程同步,并发操作怎么控制
线程同步不一定就是同时,而是协同步骤,或协同步调。线程同步就是多个线程在逻辑上互有因果关系,所以要对其执行顺序进行协调。

线程并发是指同一时间间隔内,多个线程同时执行。如果线程在时间上能够区分,那么就可以上线程休眠指定的时间来进行同步,可用sleep()方法完成。如果线程在时间上不能区分,但在逻辑顺序上可以区分的话,那么可用jion()方法来完成,一个先执行完,然后执行另一个。如果线程设计较为复杂,那么就只有通过wait(),notify()方法来完成了

十八、描述struts的工作流程。

简略过程就是web应用启动,接收用户请求并进行匹配,返回用户请求信息。

  1. 在web应用启动时,加载并初始化ActionServlet,ActionServlet从struct-config.xml文件中读取配置信息,把它们存放到各个配置对象中。

  2. 当ActionServlet接收到一个客户请求时,首先检索和用户请求相配的ActionMapping实例,如果不存在,返回用户请求路径无效信息。

  3. 如ActionForm实例不存在,则创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中。

  4. 根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的Validate()方法。如果Valiedate()方法返回null或返回一个不包含ActionMessage的ActionErrors对象,则表示表单验证成功。

  5. ActionServlet更加ActionMapping实例包含的映射信息决定请请求转发给哪个Action。如果相应的Action实例不存在,则先创建这个实例,然后调用Action的execute()方法。

  6. Action的execute()方法返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指向的JSP组建。

  7. ActionForward对象指向的jsp组件生成的动态网页,返回给客户。

十九、Tomcat的session处理,如果让你实现一个tomcatserver,如何实现session机制?

当一个session开始时,Servlet容器会创建一个HttpSession对象,在某些情况下把这些HttpSession对象从内存中转移到文件系统中或数据库中。需要访问的时候将它们载入到内存中。这样的好处就是节省内存,当web服务器产生故障时,还可以从文件系统或数据库中恢复Session的数据。
管理session有两个类:
1)StandardManager,这是一个默认的类,当tomcat启动或重载时将会session对象保存到指定文件中。2)PersistentManager,管理方式更加灵活,具有容错能力,可以及时把Session备份到Session Store中,可以控制内存中Session的数量。

二十、关于Cache(Ehcache,Memcached)
Memcache:分布式内存对象缓存系统,占用其他机子的内存。很多互联网,负载均衡三台(以三台为例)web服务器可以共享一台Memcache的资源。传递的信息以键值对的形式存储。传递的数据要实现序列化(若机器宕机,数据不可恢复)。

Oscache:页面级缓存(网上强调最多的东西),占用本机的内存资源。可 以选择缓存到硬盘,如存取到硬盘重启服务也可重新获得上次持久化的资源,而如果缓存到内存就不行。一般没必要缓存到硬盘,因为I/O操作也是比较耗资源,和从数据库取往往优势很小。Oscache存取数据的作用域分为application和session两种。

EhCache:Hibernate缓存,DAO缓存,安全性凭证缓存(Acegi),Web缓存,应用持久化和分布式缓存。EhCache在默认情况下,即在用户未提供自身配置文件ehcache.xml或ehcache-failsafe.xml时,EhCache会依据其自身Jar存档包含的ehcache-failsafe.xml文件所定制的策略来管理缓存。如果用户在classpath下提供了ehcache.xml或ehcache-failsafe.xml文件,那么EhCache将会应用这个文件。如果两个文件同时提供,那么EhCache会使用ehcache.xml文件的配置。

二一、sql的优化相关问题(避免全表查询,数据量大时使用索引)

  1. 对查询优化,避免全表扫描

  2. 尽量避免where子句中对段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描。

  3. 尽量避免where子句中出现!=或<>,否则将导致引擎放弃使用索引而进行全表扫描。

  4. 尽量避免where子句中出现or来连接条件。

  5. 慎用in和not in,否则导致全表扫描

  6. where中不要用函数操作。

  7. Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。

  8. 对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。

  9. 尽可能的使用 varchar/nvarchar 代替 char/nchar,节省空间,提高查询效率

  10. select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的。

二二、oracle中 rownum与rowid的理解,一千条记录我查200到300的记录怎么查?

rownum和rowid都是伪列,但是两者的根本是不同的,rownum是根据sql查询出的结果给每行分配一个逻辑编号,但是rowid是物理结构上的,在每条记录insert到数据库中时,都会有一个唯一的物理记录 。查询效率上 rownum 要大于rowid ,因为 通过rowid 遍历了更多的数据。
首先将一千条记录排序 ,可以按照时间倒叙排序 然后 加上关键字 between rownum and 终止rownum
select *
from (select rownum rn, a.* from emp a) t
where t.rn between 200 and 300;

二三、如何分析ORACLE的执行计划?
https://blog.51cto.com/xiao1ang/1900950(如何查看执行计划,并根据执行计划优化sql)

二四、 DB中索引原理,种类,使用索引的好处和问题是什么?

原理:因为检索磁盘比对数据,需要大量的时间和IO,所以就需要构造某列的数据的btree、hash值、位图索引。一般的索引能快速的查找比对,而索引的值记录了磁盘的位置,直接读取数据库字段对应位置的内容。

索引好处:加快数据检索速度、加速表与表之间的连接特别是实现数据的参考完整性方面有特别的意义、减少查询中分组和排序的时间,使用优化隐藏器,提高系统性能。

缺点:创建和维护索引需要时间,索引需要占用物理空间,当对表中的数据惊醒增删改时所有也需要动态维护。

二五、JVM垃圾回收实现原理。垃圾回收的线程优先级?
JVM的堆空间中主要分为年轻代、年老代和永久代。
年轻代和年老代是存储动态产生的对象。永久代主要是存储java类信息(native对象,操作非java方法用),包括解析得到的方法属性、字段等等。永久代基本不参与垃圾回收。年轻代分为一个eden区和两个相同的survior区。刚开始创建的对象都放置在eden区。这样主要是为了将生命周期短的对象尽量留在年轻代中。当eden区申请不到空间时,进行minorGC,把存活的对象拷贝到survior。年老代主要存放生命周期比较长的对象,如缓存对象。具体JVM垃圾回收过程如下:

1、对象在Eden区完成内存分配。
2、当Eden区满了,在创建对象就会申请不到空间,则触发minorGC,进行young(eden区和1survivor区的垃圾回收)。
3、在minorGC时,Eden不能被回收的对象被放入到空的survior2(即Eden肯定被清空),survivor1里不能被GC回收的地想也会被放入到这个survivor(复制所有,清理所有eden区),始终保证一个survivor是空的。
4、当完成第三步的时候、如果发现survivor满了,则这些对象呗copy到old区,或者survivor并没有满,但有些对象已经足够old了(根据GC执行的次数确定阈值,默认是15),也被放入到old区。当old区北放满之后,进行fullGC。

二六、jvm 最大内存设置。设置的原理。结合垃圾回收讲讲。

JVM内存可以分为堆内存和非堆内存,堆内存给开发人员用的,非堆内存给JVM本身用的,用来存放类型信息,即使GC时也不会释放空间。

堆内存设置:

-Xms 初始堆内存,默认物理内存1/64,也是最小分配堆内存,当空余堆内存小于40%时,会增加到-Xms的最大限制。

-Xmx 最大堆内存分配,默认物理内存1/4,当空余堆内存大于70%时,会减小打-Xms的最小限制。

非堆内存设置:

-XX:PermSize 非堆内存的初始值,默认物理内存的1/64,也是最小非堆内存。

-XX:MaxPermSize 非堆内存最大值,默认物理内存的1/4。

查看堆大小命令为Runtime.getRuntime().maxMemory()。

二七、jvm怎样通过参数调整内存大小?

本地环境变量中JVM参数设置:

new一个JAVA_OPTS:

variable name: JAVA_OPTS

variable value: -Xms256M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M

eclipse中参数设置:在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m

二八、进程与线程的区别?

线程是进程的一个单元,也是进程内的可调度实体。区别就是:
1、进程内的线程共享地址空间,进程则自己独立的地址空间。
2、进程是资源分配和拥有的单位,同一个进程内的线程共享进程资源。
3、线程是处理器调度的基本单位。
4、两者均可并发执行。

二九、怎样避免死锁

  1. 使用事务时,尽量缩短事务idea逻辑处理过程,及早提交或回滚事务

  2. 设置死锁的超时参数为合理范围,如3-10分钟,若超过时间,自动放弃本次操作,避免进程悬挂。

  3. 优化程序,检查并避免死锁现象出现。

  4. 对所有的脚本和sp(Structured Programming 结构化编程)都要仔细测试。

  5. 所有的sp(Structured Programming 结构化编程)都要有错误处理。

  6. 一般不要修改sql事务的默认级别。不推荐强行加锁。

三十、垃圾回收算法使用的产品、场景

标记-清除算法:标记阶段,确定所有要回收的对象,并标记,清除阶段则将需要回收的对象清除(eg :fullgc 清理老年代区时 根据gc年龄清除)。

复制算法:把内存分为大小相等的两块,每次使用其中的一块,当垃圾回收时,把存活的对象复制到另一块上,然后把这块内存整个清理掉。两块内存比是8:1(eg:minorGC 清理少年代时 将 eden区和survivor1区存活的对象 复制到 survivor2区,并清空eden区 和survivor区。其中 eden :survivor 1+survivor 2=8:1)

标记整理算法:把存活的对象往内存的一端移动,然后直接回收边界以外的内存。标记-整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。

分代回收算法:根据对象的存活时间把内存分为新生代和老年代,根据各代对象的存活特点,每代采用不同的GC算法。新生代用标记-复制算法,老年代用标记-整理算法。

三一、实际项目中JVM调优?

1、JVM启动参数:调整各代的内存比例和垃圾回收算法,提高吞吐量(吞:堆中对象创建,吐:gc:回收垃圾对象)。

2、改进程序逻辑算法,提高性能。

3、自定义封装线程池,解决用户响应时间长的问题。比如设置线程最小数量、最大数量。

4、连接池

三二、jdk并发包的集合介绍

Map并发包,其实现为ConcurrentHashMap,它实现了ConcurrentMap接口。put方法为根据计算出的hash值去获取segment对象。找到segment对象后调用该对象的put方法完成操作。segment中的put方法则是先加锁,之后判断数组大小,然后觉得是否扩充。然后得到key索要放置的位置。

List并发包,客在高并发环境下使用CopyOnWriteArrayList代替ArrayList。添加元素是利用数组的copy功能和加锁机制。并发情况下,CopyOnWriteArrayList比ArrayList略快了些。

set并发,CopyOnWriteSet和CopyOnWriteArrayList底层实现差不多就是在添加元素时会进行唯一性判断,如果对象数组已经含有重复的元素,不进行增加处理。

queue并发,并发类是ArrayBlockingQueue,底层为数组,并对关键的方法入队、出队操作加入了锁队机制。

Atomic系列类,比如AtomicInteger类,通过使用计数器操作时,一般为了避免线程安全问题,在方法上加锁操作。有了并发包下的原子系列类,我们就可以直接使用。

三三、线程之间的通信
参考资料
线程之间的通信 https://www.cnblogs.com/hapjin/p/5492619.html
https://www.cnblogs.com/Wenxu/p/7979023.html
java中锁的分类
https://www.cnblogs.com/qifengshi/p/6831055.html

主要包括互斥锁、条件变量、读写锁和线程信号灯。

互斥锁:以排他方式防止数据被并发修改。互斥锁两个状态0和1。具体为申请锁、占用锁以防止数据被修改,此时默认阻塞等等,最后释放锁。

条件变量通信机制:原理,条件变量出现时,可以弥补互斥锁的缺陷,有些问题仅仅依靠互斥锁无法解决。但条件变量不能单独使用,必须配合互斥锁一起实现对资源的互斥访问。

读写锁:在对数据读写时,往往读占主要部分。基本原则是如果其他线程读数据,则允许其他线程执行读操作,但不允许写操作。如果有其他线程申请写操作,则其他线程不能申请读操作和写操作。

线程信号:线程拥有与信号相关的私有数据——线程信号掩码。线程可以向别的线程发送信号,每个线程可以设置自己的阻塞集合。所有线程中,同一信号子任何线程里的对该信号的处理一定相同。

三四、介绍threadlocal

可以叫做线程本地变量或线程本地存储。ThreadLocal为变量在每个线程中都创建了一个副本,每个线程都可以访问自己内部的副本变量。但可能这样做会导致内存占用较大。

ThreadLocal类的几个方法:get() 用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,remove()用来一冲当前线程中的变量副本,initialValue()一般用来在使用时进行重写,是一个延迟加载方法。最常见的ThreadLocal使用场景是用来解决数据库连接、Session管理等。

三五、jdbc的操作过程

加载数据库驱动包、连接数据库、使用sql语句操作数据库、关闭数据库连接

三六、HTTP1.1的新特性

支持持续连接,通过建立一个TCP后,发送请求并得到响应,然后发送更多的请求并得到更多的响应。通过把简历和释放TCP连接的开销分摊到多个请求上,则对每个请求而言,优于TCP而造成的相对开销被大大降低。而且还可以发送流水线请求。

三七、异常处理,包含了什么

参考:http://lavasoft.blog.51cto.com/62575/18920/

三八、堆排序与快速排序

View Code

View Code

堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有一定的可能性会产生最坏划分,时间复杂度可能为O(n^2)。堆排比较的几乎都不是相邻元素,对cache极不友好。数学复杂度并不一定代表实际运行的复杂度。

三九、Collection有哪些类

Set, List, Map, SortedSet, SortedMap, HashSet, TreeSet, ArrayList, LinkedList, Vector, Collections, Arrays, AbstractCollection

四十、Hashcode总为1会怎样,如何解决hash冲突

当所有对象Hashcode返回都为1时,所有对象都出现hash冲突,其性能会下降

解决hash冲突:

线性再散列法、插入元素时,如果发生冲突,算法会简单的遍历hash表,直到找到表中的下一个空槽,并将该元素放入该槽中。查找元素时,首先散列值所指向的槽,如果没有找到匹配,则继续遍历hash表,直到:(1)找到相应的元素;(2)找到一个空槽(指示查找的元素不存在);(3)整个hash表遍历完毕(指示该元素不存在并且hash表是满的)。

非线性再散列法、线性再散列法是从冲突位置开始,采用一个步长以顺序方式遍历hash表,来查找一个可用的槽,从上面的讨论可以看出,它容易产生聚集现象。非线性再散列法可以避免遍历散列表,它会计算一个新的hash值,并通过它跳转到表中一个完全不同的部分。

外部拉链法、将hash表看作是一个链表数组,表中的每个槽要不为空,要不指向hash到该槽的表项的链表。

四一、如何用两个队列实现栈

即可以将A队列作为栈push,B队列作为栈pop。量队列数据相同。

四二、Object的通用方法

通用方法有equals(), finalize(), toString(), 其他native方法有hashcode(), registerNatives(), getClass(), clone(), notify(), notifyAll(), wait()等。

四三、Java中如何实现多态

多态是OOP中的一个重要特性,主要用来实现动态联编,程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。有利于提高大型系统的灵活性和扩展性。

多态的三个必要条件:有继承、有方法重写、父类引用指向子类对象。

引用变量的两种类型:编译时类型由申明类型决定,运行时类型由实际对应的对象决定。

View Code

View Code

多态内存:

四四、Java内存泄漏

内存泄漏一般情况下有两种情况:C++/C语言中,在堆中分配的内存,没有将其释放掉就删除了所有能访问到这块内存的方式全部删除。(如指针重新赋值)

另一种情况就是在内存对象已经不需要时,还保留这块内存和它的访问方式(引用),由于Java中GC机制,所以Java中的内存泄漏通常指第二种情况。

尽管对于C/C++中的内存泄露情况来说,Java内存泄露导致的破坏性小,除了少数情况会出现程序崩溃的情况外,大多数情况下程序仍然能正常运行。但是,在移动设备对于内存和CPU都有较严格的限制的情况下,Java的内存溢出会导致程序效率低下、占用大量不需要的内存等问题。这将导致整个机器性能变差,严重的也会引起抛出OutOfMemoryError,导致程序崩溃。

在不涉及复杂数据结构情况下,Java内存泄漏表现为一个内存对象的生命周期超出程序需要它的长度。(称为对象游离)。

内存泄漏实例:Java堆溢出、虚拟机栈和本地方法栈溢出、方法区和运行时常量池溢出、本机直接内存溢出

四五、final字段总结

  1. final类不能被继承,其中的方法也是默认final类型,没有子类。

  2. final方法不能被子类覆盖,但可以继承

  3. final变量表示常量,只能被赋值一次赋值后不改变

  4. final不能用于构造方法

四六、override(重写)和overload(重载)区别

override:子类在继承父类时,子类可以定义某些方法与父类的方法名称、参数个数、类型、顺序、返回值类型一致,但调用时自动调用子类的方法,父类相当于被覆盖了。

overload:可以表现在类的多态上,函数名相同,但其他参数个数、类型、顺序、返回值等都不相同。

四七、static关键字?
static修饰变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static修饰代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
static修饰方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
static 修饰类
java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。需要注意的是当一个内部类没有使用static修饰的时候,是不能直接使用内部类创建对象,须要先使用外部类对象点new内部类对象及(外部类对象.new 内部类())

四八、JVM的生命周期:
1、启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点。
2、运行。main()作为该程序初始线程的起点,任何其他线程均由该线程启动。
3、消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值