面试宝典-Java面试题记录

1、synchronized与ReentrantLock区别?
  • Synchronized是java语言的关键字,是原生语法层面的互斥锁,由JVM实现。

  • ReentrantLock是JDK 1.5之后提供的API层面的互斥锁,由lock()和unlock()方法配合try/finally语句块来完成。

2、synchronized(this) 与synchronized(class) 之间的区别?
  • synchronized(class) 类锁,会拦截所有线程,只能让一个线程访问。
  • synchronized(this) 对象锁,如果是同一个实例,就按顺序访问,如果是不同实例,可以同时访问。
3、ArrayList与LinkedList的区别?
  • ArrayList的实现是基于数组,LinkedList的实现是基于双向链表。
  • 对于随机访问,ArrayList优于LinkedList
  • 对于插入和删除操作,LinkedList优于ArrayList
  • LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
4、redis常用的的数据结构?
  • String(字符串)、list(链表)、set(集合)、zset(有序集合)和hash(散列表)
5、ActiveMQ、RabbitMQ、Kafka对比?
  • ActiveMQ: 实现了JMS1.1规范,可以和spring-jms轻松融合,实现了多种协议,不够轻巧(源代码比RocketMQ多),支持持久化到数据库,对队列数较多的情况支持不好。
  • RabbitMQ:比kafka成熟,支持AMQP事务处理,在可靠性上,RabbitMQ超过kafka,在性能方面超过ActiveMQ。
  • Kafka:设计的初衷就是处理日志的,不支持AMQP事务处理,性能(吞吐量、tps)比RabbitMQ要强。
6、springMVC的执行流程?
  1. 发起请求到前端控制器(DispatcherServlet)
  2. 前端控制器请求HandlerMapping查找 Handler
  3. 处理器映射器HandlerMapping向前端控制器返回Handler
  4. 前端控制器调用处理器适配器去执行Handler
  5. 处理器适配器去执行Handler
  6. Handler执行完成给适配器返回ModelAndView
  7. 处理器适配器向前端控制器返回ModelAndView
  8. 前端控制器请求视图解析器去进行视图解析
  9. 视图解析器向前端控制器返回View
  10. 前端控制器进行视图渲染
  11. 前端控制器向用户响应结果
7、Mysql常见的存储引擎比较?
  • InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。
  • MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。
  • MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。
8、 Spring 事务的传播属性?
  • PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
  • PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。
9、JVM的内存结构?
  1. 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
  2. :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中) 。
  3. :存放所有new出来的对象。
  4. 静态域:存放静态成员(static定义的) 。
  5. 常量池:存放字符串常量和基本类型常量(public static final)。
10、多线程的几种实现方式?

实现runable接口,实现callable接口(带有返回值),继承thread类。

11、notify()和notifyAll()的区别?
  • notify方法能够唤醒一个正在等待该对象的monitor线程,当有多个线程都在等待该对象的monitor的话,则只能唤醒其中一个线程,具体唤醒哪一个不确定。同样的调用某个对象的notify方法,当前线程也必须拥有这个对象的monitor,因此调用notify方法必须在同步代码块或者同步方法中进行
  • notifyAll方法能够唤醒所有正在等待该对象的monitor的线程。注意:此处唤醒不等于所有线程都获得该对象的monitor,至于哪个等待的线程能够获得就不确定了。
12、线程的几种状态
  1. 新建状态(New):新创建了一个线程对象。
  2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中,变得可运行,只等待获取CPU的使用权,即在就绪状态的进程除CPU之外,其它的运行所需资源都已全部获得。
  3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
  4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
    阻塞的情况分三种:
    • 等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,
    • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。
    • 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时,或者I/O处理完毕时,线程重新转入就绪状态。
  5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
13、事务的四个特性?
  • 原子性(Atomic)
    一个事务是一个不可分割的整体,为了保证事务的总体目标,事务必须具有原子性,即当数据修改时,要么全都执行,要么全都不执行。即,不允许事务部分地完成,避免了只执行这些操作的一部分而带来的错误。
  • 一致性(Consistency)
    一个事务在执行之前和执行之后,数据库数据必须保持一致性。数据库的一致性状态应该满足模式锁指定的约束条件,那么在完整执行该事务后,数据库仍然处于一致性状态。
  • 隔离性(Isolation)
    由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据库时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
  • 持久性(Durability)
    事务完成以后,DBMS(数据库管理系统)保证它对数据库中数据的修改是永久性的,当系统或介质发生故障时,该修改也永久保持。持久性一般通过数据库备份与恢复来保证。
14、事务的隔离级别?
  • 读未提交(Read Uncommitted):只处理更新丢失。如果一个事务已经开始写数据,则不允许其他事务同时进行写操作,但允许其他事务读此行数据。可通过“排他写锁”实现。
  • 读提交(Read Committed):处理更新丢失、脏读。读取数据的事务允许其他事务继续访问改行数据,但是未提交的写事务将会禁止其他事务访问改行。可通过“瞬间共享读锁”和“排他写锁”实现。
  • 可重复读取(Repeatable Read):处理更新丢失、脏读和不可重复读取。读取数据的事务将会禁止写事务,但允许读事务,写事务则禁止任何其他事务。可通过“共享读锁”和“排他写锁”实现。
  • 序列化(Serializable):提供严格的事务隔离。要求失去序列化执行,事务只能一个接一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
15、Java有几种线程池?
  • newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newScheduledThreadPool:创建一个定长线程池,支持定时和周期性任务执行。
  • newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。
16、mysql索引的类型及创建方式?
  • 主键索引:主键是一种唯一性索引,但它必须指定为PRIMARY KEY,每个表只能有一个主键。
    alert table tablename add primary key(`字段名`)
    
  • 唯一索引:索引列的所有值都只能出现一次,即必须唯一,值可以为空。
    alter table table_name add unique index(`字段名`);
    
  • 普通索引:基本的索引类型,值可以为空,没有唯一性的限制。
    alter table table_name add index(`字段名`);
    
  • 全文索引:全文索引不支持中文需要借sphinx(coreseek)或迅搜技术处理中文。
    alter table 表名 add FULLTEXT(`字段名`);
    
17、hibernate 四种状态?
  • 临时状态(transient):刚用new 语句创建,还没有被持久化,并且不处于Sesssion 的缓存中。
  • 持久化状态(persistent):已经被持久化,并且加入到Session 的缓存中。
  • 删除状态(removed):不再处于Session 的缓存中,且Session 已经计划将其从数据库中删除。
  • 游离状态(detached):已经被持久化,但不再处于Session 的缓存中。
18、Servlet的生命周期?
  1. Servlet 通过调用 init () 方法进行初始化。
  2. Servlet 调用 service() 方法来处理客户端的请求。
  3. Servlet 通过调用 destroy() 方法终止(结束)。
  4. Servlet 由 JVM 的垃圾回收器进行垃圾回收。
19、介绍一下Spring?

Spring是一个分层的full-stack(一站式) 轻量级开源框架。
两大核心:

  • IOC(控制反转):控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建和维护。
  • AOP(面向切面编程):通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
20、拦截器(Interceptor)和过滤器(Filter)的区别?
  1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  6. 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,在拦截器里注入一个service,可以调用业务逻辑。
  7. Filter只在Servlet 前后起作用。而拦截器能够深入到方法前后、异常抛出前后等。
21、JVM内存划分?
  • 方法区:存储虚拟机运行时加载的类信息、常量、静态变量和即时编译的代码,因此可以把这一部分考虑为一个保存相对来说数据较为固定的部分,常量和静态变量在编译时就确定下来进入这部分内存,运行时类信息会直接加载到这部分内存,所以都是相对较早期进入内存的。
  • 堆区:是JVM所管理的内存中最大的一块。主要用于存放对象实例,每一个存储在堆中的Java对象都会是这个对象的类的一个副本,它会复制包括继承自它父类的所有非静态属性。而所谓的垃圾回收也主要是在堆区进行。 根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑是上连续的即可,就像我们的磁盘空间一样。在实现上,既可以实现成固定大小的,也可以是可扩展的。
    堆内存通常被分为三块区域:新生代内存(young generation)、老生代(old generation)、永生代(Permanent Generation for VM Matedata),Java8中把存放元数据中的永生代内存从堆内存中移到了本地内存(native memory)中,Java8中JVM堆内存结构就变成了以下所示:
    在这里插入图片描述
  • 栈区:主要存放一些对象的引用和编译期可知的基本数据类型,这个区域是线程私有的,即每个线程都有自己的栈。在Java虚拟机规范中,对这个区域规定了两种异常情况:
    • 如果线程请求的栈深度大于虚拟机锁所允许的深度,则抛出StackOverflowError异常。
    • 如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
  • 本地方法栈:本地方法在运行时存储数据产生的栈区。为JVM运行Native方法准备的空间,它和前面介绍的Java栈的作用是类似的,由于很多Native方法都是C语言实现的,所以它通常又叫C栈。和虚拟机栈一样,也会抛出StackOverflowError和OutOfMemoryError异常。
  • 程序计数器:用来记录程序运行到什么位置的,显然它应该是线程私有的。
22、GC算法?
  • 引用计数算法
    给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
  • 根搜索算法
    设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的。
  • 标记-清除算法
    标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象;然后,在清除阶段,清除所有未被标记的对象。
  • 复制算法:(新生代的GC)
    将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
  • 标记-整理算法:(老年代的GC)
    标记-压缩算法适合用于存活对象较多的场合,如老年代。它在标记-清除算法的基础上做了一些优化。和标记-清除算法一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记;但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端;之后,清理边界外所有的空间。
23、分布式锁?
  • 基于数据库的分布式锁
  • 基于 Redis 的分布式锁
  • 基于Zookeeper的分布式锁
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3.你有什么优缺点 " 【思路】:优点在这个问题上, 面试官关注的问题有两点。第一, 申请人没有撒谎, 而是真实地阐述了自己的优点。第二, 他所阐述的优点, 恰好是这个职位所需要的素质。有很多时候, 对于一个岗位而言的优点, 会成为另一个岗位的缺点。比如说, 如果你具备很强的领导能力, 往往不适合从事秘书、 助理、 客户服务代表等以细节和服务他人为主的工作。所以, 在回答这个问题的时候, 要遵从以下步骤:   (1) 找出自己的三至五个优点;   (2) 每个优点找出N多个例子, 举例最好来自学习、 工作和生活等三个方面, 而不是仅仅来自一个方面;   (3) 在这三到五个优点之中, 精选出一两个和所申请职位最吻合的优点。 缺点认识自己的缺点是一个巨大的优点, 当HR问到你缺点的时候, 你的机会来了, 请快展示你的自知之明吧!你想把优点故意包装成缺点?比方说把""对工作负责""这个优点伪装成""对自己和他人要求过高?"" 面试官会不屑一顾地批注: 这是我五年前玩剩下的把戏, 此人土冒之极。你想完全实话实说: 应聘会计的人说自己粗心?应聘销售的人说自己容易紧张?面试官会无限惋惜地批注: 此人心眼好, 老实, 但不适合我们的工作, 推荐到""实话实说""栏组任职去吧!对待这个问题, 惟一的对策就是真诚地暴露自己的弱点, 只要这个弱点不是你所申请职位的""致命伤""即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值