【打卡day04】每天学习10道java面试题

目录

1.线程池的工作流程?拒绝策略?execute和submit提交、关闭

2.有了解过TCP粘包和拆包问题?

3.BIO、NIO和AIO的区别、三种IO的原理与用法?

4.常用的jvm调优的参数都有哪些?

5.如何做mysql的性能优化?

6.rabbitmq怎么避免消息丢失?

7.spring支持几种bean的作用域?

8.spring boot 有哪些方式可以实现热部署?

9.mybatis的一级缓存和二级缓存?

10.zookeeper怎么保证主从节点的状态同步?


1.线程池的工作流程?拒绝策略?execute和submit提交、关闭

【工作流程】

  1. 线程池刚创建时,任务队列是作为参数传进来的,就算队列中有任务,线程池也不会立即执行它们。

  2. 当调用execute()方法添加一个任务时,线程池会做如下判断:

    • 如果正在运行的线程数小于核心线程数量corePoolSize,将立即创建线程运行该任务。

    • 如果正在运行的线程数大于等于corePoolSize,将该任务添加到队列;

    • 当队列满了并且线程数小于最大线程数量maximumPoolSize,将创建非核心线程运行该任务。

    • 当队列满了并且线程数等于最大线程数量maximumPoolSize,将根据拒绝策略来做响应处理。

  3. 当一个线程完成任务时,将从队列中取下一个任务进行处理。

  4. 当一个线程没有任务要执行时,且超过一定时间(keepAliveTime),判断线程数是否大于核心线程数,如果大于则将该线程销毁,当线程池的所有任务完成后,最终的线程会收缩到corePoolSize大小。

【拒绝策略】

记住5种即可:

  1. AbortPolicy:直接抛出异常

  2. CallerRunsPolicy:用调用者所在的线程来执行任务

  3. DiscardOldestPolicy:丢弃阻塞队列里最老的任务(队头任务)

  4. DisCardPolicy:直接抛弃

  5. 自定义实现拒绝策略,需要实现RejectExecutionHandler接口即可

【任务提交】

  1. execute()用于提交不需要返回值的任务,参数为Runnerable类型。

  2. submit()用于提交需要返回值的任务,线程池会返回一个future类型的对象,通过这个对象可以判断任务是否执行成功,并且可以通过future的get()方法获取返回值。

ps:FutureTask类型的get()方法会进行阻塞(原因是需要等到所有任务都完成才能获取到结果,如果有任务没有执行完,get()方法就会被阻塞),可以使用CompletionService和CompletableFuture(按照任务完成的先后顺序获取任务的结果,每次调用会返回最先执行好的任务的结果)

【关闭】

  1. shutdown()方法将线程池状态置为shutdown,并不会立即关闭:

    1. 停止接收外部submit的任务

    2. 执行完内部正在跑的任务和队列中等待的任务

    3. 关闭线程池

  2. shutdownNow()将线程池状态置为stop。

    1. 停止接收外部submit的任务

    2. 忽略队列中等待的任务

    3. 尝试将正在执行的任务interrupt中断

    4. 返回未执行的任务列表

    总结:shutdownNow()会立即停止,而shutdown()只是不再接收,但不影响内部任务(已提交任务)的执行。

2.有了解过TCP粘包和拆包问题?

【是什么】

TCP是面向流的传输协议,底层并不了解上层业务数据的具体含义,因此就会出现把多个小的应用层数据包分装成一个大的TCP数据包(粘包)或者把一个大的应用层数据包拆分成多个小的TCP数据包(拆包)进行发送。

【为什么】

  1. 要发送的数据小于TCP发送缓冲区大小,TCP将到此写入缓冲区的数据一次发送出去,将会发生粘包。

  2. 接收端的应用层没有及时读取接收缓冲区的数据,将会发生粘包。

  3. 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。

  4. 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。

【怎么解决】

  1. 发送端将每个数据包封装为固定长度

  2. 在数据尾部添加特殊字符进行分割

  3. 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段什么内容体大小。

3.BIO、NIO和AIO的区别、三种IO的原理与用法?

  1. BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

  2. NIO (New I/O):同时支持同步阻塞与同步非阻塞模式。(对应的是轮询)

  3. AIO ( Asynchronous I/O):异步非阻塞I/O模型。(对应的是状态发生改变后主动通知)

【适用场景】

  1. BIO方式适用于连接数目比较小且固定的架构

  2. NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器

  3. AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器

内容参考:BIO、NIO和AIO的区别、三种IO的原理与用法_微凉不是青风的博客-CSDN博客_aio

4.常用的jvm调优的参数都有哪些?

【常见的jvm配置参数】

例如:-Xms20m -Xmx20m -Xss256k

  1. -Xms:s为strating,表示堆内存起始大小

  2. -Xmx:x为max,表示最大的堆内存(一般来说-Xms和-Xmx的设置为相同大小,因为当heap自动扩容时,会发生内存抖动,影响程序的稳定性)

  3. -Xmn:n为new,表示新生代大小

  4. -Xss:规定每个线程虚拟机栈的大小

  5. -XX:SurvivorRator=8:表示堆内存中新生代、老年代和永久代的比为8:1:1

  6. -XX:PretenureSizeThreshold=3145728:表示当创建(new)的对象大于3M的时候直接进入老年代

  7. -XX:MaxTenuringThreshold=15:表示当对象的存活的年龄(minor gc一次加1)大于多少时,进入老年代

  8. -XX:-DisableExplicirGC: 表示是否(+表示是,-表示否)打开GC日志

内容参考链接:问十一:JVM调优常用配置参数有哪些?_问而知的博客-CSDN博客

5.如何做mysql的性能优化?

  1. 架构设计层面的优化

    • 搭建MySQL主从集群,保证服务的高可用性。

    • 读写分离设计,在读多写少的场景中,可以避免读写冲突,导致的性能问题。

    • 引入分库分表的机制,通过分库降低单个服务器的IO压力分表降低单表数据量,提升sql的查询效率。

    • 针对热点数据,可以引入更为高效的分布式数据库,如Redis,可以很好减轻MySQL的访问压力,同时能提升数据的检索性能。

  2. SQL执行优化

    • 首先确认开启了慢查询日志,然后通过慢查询日式定位到慢查询SQL

    • 执行计划分析,比如通过explain来查看当前sql的执行计划,可重点关注type、key、rows等字段,从而去定位该SQL执行慢的根本原因

    • 索引创建的不恰当或者sql语句写的不恰当等等

  3. sql优化规则

    • SQL的查询一定要基于索引来进行数据扫描。

    • 避免索引列上使用函数或者运算符。

    • Where字句中like%号尽量放置在右边。

    • 使用索引扫描,联合索引中的列从左往后,命中越多越好

    • 尽可能使用SQL语句用到的索引完成排序

    • 查询有效的列信息即可,少用*代替列信息

    • 永远要用小的结果集驱动大的结果集

内容参考链接:MySQL性能优化_程序猿-清风的博客-CSDN博客_mysql性能调优

6.rabbitmq怎么避免消息丢失?

  1. 生产端发送消息时,由于网络闪断原因,消息未到达mq

    这种情况可以立即进行重试,但是一般也会失败。因为网络闪断的特性就是间歇性,较短时间内的重试大概率会失败。这个时候,需要我们对发送失败的消息做出补偿。

  2. 生产端发送消息成功,mq也接收到了消息,刚准备处理时,mq宕机

    mq提供了两种方式

    (1)事务机制,属于同步方式,消息发送完之后会阻塞等待mq回应。在此期间无法发送下一条消息,严重降低吞吐量与性能。

    (2)confirm确认机制,属于异步方式,消息发送完之后不需要阻塞等待。当消息达到指定的队列后,mq将会主动回传一个ack,代表消息入队成功。

    mq收到信息不是立刻通知生产端,而是在持久化完成后再通知生产端,开启队列的confirm机制,即mq会对落盘后的消息进行异步ack。

  3. mq落盘后ack,但由于网络闪断,生产端未收到ack

    1、生产端首先将业务数据以及消息数据入库,需要在同一个事务中,消息数据入库失败,则整体回滚。

    2、假设生产端此时将a,b,c三条数据入库,他们的状态都为发送中。

    3、mq收到了a消息,mq落盘后回传ack,生产端接收到了ack后,将消息库中的a删除

    4、mq接着收到了b消息,但回传ack时,由于网络闪断一直未能让生产端接收到。此时定时任务会根据预设的超时时间扫描到发送超时或mq处理超时的消息,对其进行重试。重试成功后,生产端对其进行删除。当消费的时候,首先得查询出生产端的消息表中的消息库(即补偿那些未成功的数据,不会特别多)

    5、c消息就没有这么好运,由于其他原因,比如路由键设置错误、队列被误删除等,始终无法路由到对应的队列中,导致重试一直失败。在达到最大次数后,将会进行报警通知,后续由人工处理。

  4. 队列本身可能丢失消息

    1、消息达到mq,但mq中出现内部错误,无法处理该消息

    2、消息还没来得及刷盘,mq就宕机了,重启后,消息丢失。

    3、开启持久化后,但是硬盘坏了,无法恢复数据。

    解决方案:前两种都可以通过落盘后的异步ack解决,第3中情况需要通过搭建高可用的集群解决。

  5. 消费端可能丢失消息

    1、消费端采用自动ack机制,还没有处理完毕,消费端宕机。

    改成手动ack,当消息处理完后再通知mq。

    2、消费端处理完消息后,回传ack时发生网络闪断,mq未收到ack。

    mq会将超时未ack的消息重新放回队列。

  6. 注意点

    • mq的ack回传是批量异步的方式,生产端对ack的监听也是异步的,否则变成同步方式的话,效率很低。

    • 在重试的补偿机制下,消费端需要保证幂等。

内容图片参考来自:RabbitMQ如何在各个环节保证消息不丢失_SunAlwaysOnline的博客-CSDN博客_rabbitmq如何保证消息不丢失,大佬写得非常棒,在此强烈推荐阅读原文!

7.spring支持几种bean的作用域?

  1. singleton:单例

  2. prototype:原型模式,每次都会重新创建一个实例

  3. request(HTTP请求):每次http请求都会创建一个bean,

  4. session(会话):在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

  5. global-session(全局会话):在一个全局的HTTP Session中,一个bean定义对应一个实例。

ps:后面三种作用域仅在基于web的Spring ApplicationContext情形下有效。

8.spring boot 有哪些方式可以实现热部署?

基本原理都是重新加载,比如定时创建类加载器实现重新加载,或者某个操作触发重新创建类加载器加载

  1. spring-boot-devtools

  2. idea的热部署功能

  3. Jrebel

内容参考来自:Springboot热部署的三种方式_四叶猫的博客-CSDN博客_springboot热部署,具体详情推荐阅读原文

9.mybatis的一级缓存和二级缓存?

【一级缓存】作用域是sqlsession级别的,同一个sqlsession中执行相同的sql查询,是基于PrepetualCache的HashMap本地缓存,默认是开启以及缓存的。

【二级缓存】是sqlsesionFactory对象的缓存,有同一个sqlsessionFactory创建的sqlsession共享二级缓存。

内容参考来自:mybatis的一级缓存和二级缓存_哪 吒的博客-CSDN博客_mybatis一级缓存二级缓存,何时清除情况等详细信息推荐查看原文

10.zookeeper怎么保证主从节点的状态同步?

Zookeeper 的核心是原子广播机制,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。

【恢复模式】 当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。

【广播模式】 一旦 leader 已经和多数的 follower 进行了状态同步后,它就可以开始广播消息了,即进入广播状态。这时候当一个 server 加入 ZooKeeper 服务中,它会在恢复模式下启动,发现 leader,并和 leader 进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper 服务一直维持在 Broadcast 状态,直到 leader 崩溃了或者 leader 失去了大部分的 followers 支持。

内容参考来自:ZooKeeper详解_辽宁吴奇隆的博客-CSDN博客_zookeeper主从同步,更多zookeeper知识推荐阅读原文

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值