史上最全的中高级JAVA工程师面试题及答案(二)_极悦注册
专注Java教育14年 全国咨询/投诉热线:444-1124-454
极悦LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 史上最全的中高级JAVA工程师面试题及答案(二)

史上最全的中高级JAVA工程师面试题及答案(二)

更新时间:2019-10-18 11:32:41 来源:极悦 浏览5696次

  

今天极悦java培训机构小编为大家汇总了史上最全的中高级JAVA工程师面试题及答案(二),分别是java线程池面试题、java jvm 面试题、Zookeeper面试题、Mysql面试题及Mysql性能诊断和优化面试题,希望能够帮助到正在找工作的中高级JAVA程序员,下面就随小编一起来看看吧。


史上最全的中高级JAVA工程师面试题及答案


java线程池面试题


  25、Executors框架的四种线程池及拒绝策略


  四种线程池


  ExecutorService executorService =固定大小线程池


  Executors.newFixedThreadPool(60); 设置固定值会造成高并发线程排队等待空闲线程,尤其是当读取大数据量时线程处理时间长而不释放线程,导致无法创建新线程。


  可缓存线程池 Executors.newCachedThreadPool(); 线程池无限大,而系统资源(内存等)有限,会导致机器内存溢出OOM。


  定长且可定时、周期线程池 Executors.newScheduledThreadPool(5);


  单线程线程池 Executors.newSingledThreadPool();


/* 自定义线程池。

         * 构造参数:

         * public ThreadPoolExecutor(

             * int corePoolSize,--当前线程池核心线程数

             * int maximumPoolSize,--当前线程池最大线程数

             * long keepAliveTime,--保持活着的空间时间

             * TimeUnit unit,--时间单位

             * BlockingQueueworkQueue,--排队等待的自定义队列

             * ThreadFactoty threadFactory,

             * RejectedExecutionHandler handler--队列满以后,其他任务被拒绝执行的方法

         * ){.........}


  在使用有界队列时,若有新的任务需要执行,


  (1)若线程池实际线程数小于corePoolSize,则优先创建线程,


  (2)若大于corePoolSize,则会将任务加入队列,


  (3)若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,


  (4)若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。


  JDK拒绝策略


  (1)AbortPolicy:默认,直接抛出异常,系统正常工作。


  (2)DiscardOldestPolicy:丢弃最老的一个请求,尝试再次提交当前任务。


  (3)CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。用线程池中的线程执行,而是交给调用方来执行, 如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行


new ThreadPoolExecutor(   

   2, 3, 30, TimeUnit.SECONDS,    

    new SynchronousQueue(),    

    new RecorderThreadFactory("CookieRecorderPool"),    

     new ThreadPoolExecutor.CallerRunsPolicy());  


  (4)DiscardPolicy:丢弃无法处理的任务,不给予任何处理。


  (5)自定义拒绝策略 如果需要自定义策略,可以实现RejectedExecutionHandler接口。


  26、Reactor模式


Reactor单线程模型


1_meitu_1.jpg

  

2_meitu_2.jpg


一个Acceptor线程,监听Accept事件,负责接收客户端的连接SocketChannel,SocketChannel注册到Selector上并关心可读可写事件。一个Reactor线程,负责轮训selector,将selector注册的就绪事件的key读取出来,拿出attach任务Handler根据事件类型分别去执行读写等。


  单线程模型的瓶颈:比如:拿一个客户端来说,进行多次请求,如果Handler中数据读出来后处理的速度比较慢(非IO操作:解码-计算-编码-返回)会造成客户端的请求被积压,导致响应变慢!所以引入Reactor多线程模型!


  Reactor多线程模型


1.png


2_meitu_4.jpg


Reactor多线程就是把Handler中的IO操作,非IO操作分开。操作IO的线程称为IO线程,操作非IO的线程叫做工作线程。客户端的请求(IO操作:读取出来的数据)可以直接放进工作线程池(非IO操作:解码-计算-编码-返回)中,这样异步处理,客户端发送的请求就得到返回了不会一直阻塞在Handler中。但是当用户进一步增加的时候,Reactor线程又会出现瓶颈,因为Reactor中既有IO操作,又要响应连接请求。为了分担Reactor的负担,所以引入了主从Reactor模型!


  主从Reactor模型


3.png


4_meitu_6.jpg


  主Reactor用于响应连接请求,从Reactor用于处理IO操作请求!  


特点是:服务端用于接收客户端连接的不再是1个单独的NIO线程(Acceptor线程),而是一个独立的NIO线程池。  


Acceptor线程池接收到客户端TCP连接请求处理完成后(可能包含接入认证等),将新创建的SocketChannel注册到I/O线程池(sub reactor线程池)的某个I/O线程上,由它负责SocketChannel的读写和编解码工作。

Acceptor线程池只用于客户端的登录、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的I/O线程上,有I/O线程负责后续的I/O操作。  


第三种模型比起第二种模型,是将Reactor分成两部分,mainReactor负责监听server socket,accept新连接,并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网 络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同。



  java jvm 面试题


  27、Object的内存布局


  

5_meitu_7.jpg

  28、方法区卸载Class的条件


  (1)该类所有的实例已经被回收 


(2)加载该类的ClassLoader已经被回收 


(3)该类对应的java.lang.Class对象没有任何地方被引用


  Ps:方法区除了回收无用class,也回收废弃常量,即没有被引用常量


  29、可以作为GC Roots的对象包括哪些


  (1)虚拟机栈(栈帧中的局部变量表)中引用的变量 


(2)方法区中类静态属性引用的对象 


(3)方法区中常量引用的对象 


(4)本地方法栈中JNI引用的变量


  30、JVM运行时内存模型


  方法区、堆、虚拟机栈、本地方法栈、程序计数器


  31、Netty的ByteBuffer的引用计数器机制


  从netty的4.x版本开始,netty使用引用计数机制进行部分对象的管理,通过该机制netty可以很好的实现自己的共享资源池。如果应用需要一个资源,可以从netty自己的共享资源池中获取,新获取的资源对象的引用计数被初始化为1,可以通过资源对象的retain方法增加引用计数,当引用计数为0的时候该资源对象拥有的资源将会被回收。


  32、判断对象是否存活的两种方法


  (1)引用计数法:缺点是对循环引用的对象无法回收 


(2)可达性分析


  33、Java对象的初始化过程

6_meitu_8.jpg

34、类加载双亲委派模型


  从上到下分三个类加载器:


  BootStrap classloader:启动类加载器,负责将Java_HOME/lib下的类库加载到虚拟机内存中,比如rt.jar Extension classloader:扩展类加载器,负责将JAVA_HOME/lib/ext下的类库加载到虚拟机内存中。


 Application classloader:应用程序类加载器,负责加载classpath环境变量下指定的类库。如果程序中没有自定义过类加载器,那么这个就是程序中默认的类加载器。


  双亲委派模型:


  如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。


7_meitu_9.jpg


  防止自定义的一些跟jdk标准库中冲突的全限定名的类被加载,导致标准库函数不可用。



  Zookeeper面试题


  35、Zookeeper的常用应用场景有哪些


  分布式锁:获取父节点下的最小节点作为获得锁的一方


  命名服务:通过在zookeeper节点下创建全局唯一的一个path


  配置管理:配置放在zk上,所有应用监听节点改变。


  集群管理:GroupMembers集群管理,是否有机器退出和加入


  36、Zookeeper的分布式数据一致性算法


  •ZAB原子消息广播协议*。


  一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。


  37、Zookeeper数据同步的简单描述


  在ZooKeeper中所有的客户端事务请求都由一个主服务器也就是Leader来处理,其他服务器为Follower,Leader将客户端的事务请求转换为事务Proposal,并且将Proposal分发给集群中其他所有的Follower,然后Leader等待Follwer反馈,当有过半数(>=N/2+1)的Follower反馈信息后,Leader将再次向集群内Follower广播Commit信息,Commit为将之前的Proposal提交;


  38、ZK集群最少需要几台机器?


  三台,2N+1,保证奇数,主要是为了leader选举算法中的“超过半数有效(>=N/2+1)”


  38、Zookeeper和Eureka的区别


  ZK保证Cp,即一致性,分区容错性,比如当master节点因为网络故障和其他节点失去联系的时候,剩余节点会重新进行Master选举。问题在于Master选举的时间太长30~210s,选举期间整个zk集群是不可用的,这就导致选举期间的注册服务瘫痪。  


Eureka保证Ap,高可用性,它没有所谓主从节点概念,各节点平等。某节点挂掉不影响其他节点功能,其他节点照样提供查询和注册功能。Eureka客户端发现Eureka节点挂掉直接切换到其他正常的节点上去。只不过可能查到的数据不是最新的,也就是Eureka不保证数据的强一致性。  


作为注册中心,推荐Eureka,因为注册服务更重要的是可用性。



  Mysql面试题


  39、InnoDB和MyISAM存储引擎的区别


  Starting from MySQL 5.5.5, the default storage engine for new tables isInnoDB rather than MyISAM.


1571368412171318.jpg


  40、Btree索引和Hash索引的区别


  Btree索引适合范围查找,Hash索引适合精确查找


  41、数据库的ACID特性


  数据库事务必须具备ACID特性


 原子性:Atomic,所有的操作执行成功,才算整个事务成功 


一致性:Consistency,不管事务success或fail,不能破坏关系数据的完整性以及业务逻辑上的一致性 


隔离性:Isolation,每个事务拥有独立数据空间,多个事务的数据修改相互隔离。事务查看数据更新时,数据要么是另一个事务修改前的状态,要么是修改后状态,不应该查看到中间状态数据。


持久性:Durability,事务执行成功,数据必须永久保存。重启DB,数据需要恢复到事务执行成功后的状态。


原子性、一致性、持久性DBMS通过日志来实现。  隔离性DBMS通过锁来实现


  42、Mysql数据库的隔离级别


1571368542545779.jpg


  43、Select For Update使用场景


  select for update 的使用场景,为了避免自己看到的数据并不是数据库存储的最新数据并且看到的数据只能由自己修改,需要用 for update 来限制。


  44、分布式事务模型之XA和TCC的区别和联系?


  XA-DTP模型


  最早的分布式事务模型是 X/Open 国际联盟提出的 X/Open Distributed Transaction Processing(DTP)模型,也就是大家常说的 X/Open XA 协议,简称XA 协议。  


DTP 模型中包含一个全局事务管理器(TM,Transaction Manager)和多个资源管理器(RM,Resource Manager)。全局事务管理器负责管理全局事务状态与参与的资源,协同资源一起提交或回滚;资源管理器则负责具体的资源操作。


  TCC模型


  TCC(Try-Confirm-Cancel)分布式事务模型相对于 XA 等传统模型,其特征在于它不依赖资源管理器(RM)对分布式事务的支持,而是通过对业务逻辑的分解来实现分布式事务。Try-Confirm-Cancel Try 操作对应2PC 的一阶段准备(Prepare);Confirm 对应 2PC 的二阶段提交(Commit),Cancel 对应 2PC 的二阶段回滚(Rollback),可以说 TCC 就是应用层的 2PC。


  45、Mysql-binlog日志复制方式


  (1)基于段的复制 记录的是执行的语句


(2)基于行的复制 记录是表中每一行的操作 


(3)混合复制


  46、mysql主从复制原理


  1571368792836343.jpg


  从服务器的IO线程读取主服务器的二进制日志变更,写入到中继日志relaylog中,如果IO线程追赶上了主服务器的日志,则进入sleep状态,直到主服务器发送唤醒信号,从服务器上的SQL线程重放relaylog中的日志。


  47、基于日志点的复制和GTID的复制有何区别?


  基于日志点的复制:从主服务器的哪个二进制日志的偏移量进行增量同步,如果指定错误会造成遗漏或重复。 


基于GTID的复制:从服务器会告诉主服务器,已经在从服务器上已经执行完了哪些gtid值,然后主库会把从库未执行的事务gtid值发送给从库执行。同一个事务只在指定的从库上执行一次。



  Mysql性能诊断和优化面试题


  48、聚簇索引和非聚簇索引的区别


  聚簇索引:就是指主索引文件和数据文件为同一份文件,聚簇索引主要用在Innodb存储引擎中。如主键。B+Tree的叶子节点上的data就是数据本身。 


非聚簇索引:就是指B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址


  49、消费者宕机:怎么保证消息队列消息不丢失?


  比如activemq或者rabbitmq生产者消息投递到消息队列后,消费者拿到消息后,默认是自动签收机制,消息队列将删除这条消息,但是如果仅仅是拿到但是没有来得及处理业务逻辑时,消费者就宕机,那么此消息将会丢失,以后也不会再收到。 


解决办法:消费端要设置签收机制为手动签收,只有当消息最终被处理,才告诉消息队列已经消费,此时消息队列再删除这条消息。


  50、MQ集群宕机:怎么保证消息不丢失?


  生产者投递消息到mq服务器,如果不保证消息和队列的持久化,那么当mq宕机时消息将彻底丢失,所以需要对消息做持久化存储,可以存储到磁盘或者数据库中,当mq服务器恢复时,消费端可以继续消费mq服务器中的消息。


  但是,比如RabbitMQ的消息持久化,是不承诺100%的消息不丢失的!  


原因:因为有可能RabbitMQ接收到了消息,但是还没来得及持久化到磁盘,他自己就宕机了,这个时候消息还是会丢失的。如果要完全100%保证写入RabbitMQ的数据必须落地磁盘,不会丢失,需要依靠其他的机制。



  Spring源码面试题


  51、springmvc如何解决循环依赖的问题


  当使用构造器方式初始化一个bean,而且此时多个Bean之间有循环依赖的情况,spring容器就会抛出异常! 解决办法:初始化bean的时候(注意此时的bean必须是单例,否则不能提前暴露一个创建中的bean)使用set方法进行注入属性,此时bean对象会先执行构造器实例化,接着将实例化后的bean放入一个map中,并提供引用。当需要通过set方式设置bean的属性的时候,spring容器就会从map中取出被实例化的bean。比如A对象需要set注入B对象,那么从Map中取出B对象即可。以此类推,不会出现循环依赖的异常。


  52、spring事务的传播行为和隔离级别


  spring事务七个事务传播行为


  在TransactionDefinition接口中定义了七个事务传播行为:


  PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。


  PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。


  PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。


  PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。


  PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。


  PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常


  PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行


  Spring事务的五种隔离级别


  在TransactionDefinition接口中定义了五个不同的事务隔离级别


  ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别. 另外四个与JDBC的隔离级别相对应


  ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读


  ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。


  ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。


  ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。


timg (3).jpg


以上就是动力java培训机构小编介绍的“史上最全的中高级JAVA工程师面试题及答案(二)”的内容,希望对大家有帮助,更多java最新面试题请继续关注极悦java培训机构官网,每天会有精彩内容分享与你。


由于“史上最全的中高级JAVA工程师面试题及答案”内容太多,本文已满,请看下文链接:


1~24道中高级JAVA工程师面试题及答案请看链接:


53~64道中高级JAVA工程师面试题及答案请看链接:


相关推荐









提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>