Java面试
2024-02-20 18:00:51 1 举报
AI智能生成
登录查看完整内容
Java面试宝典
作者其他创作
大纲/内容
反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;
1 获取想要操作类的Class对象
2 调用Class类中的方法
3 使用反射API操作这些信息
反射使用步骤
Java反射
spring 是一个开源的轻量级 JavaBean 容器框架,降低了应用开发的复杂性
有ioc控制反转,依赖注入松耦合
AOP面向切面
方便集成
谈谈Spring框架
IOC是一种设计思想,从下层控制上层反转到→上层控制下层;通过依赖注入实现
把创建和查找依赖对象的控制权交给 IoC 容器,由 IoC 容器进行注入、组合对象。这样对象与对象之间是松耦合、便于测试、功能可复用
什么是IOC
AOP是一种面向切面,切开对象的封装,把影响类的公共行为封装到一个可重用的模块中,组成一个切面,代码复用,降低耦合
动态代理
静态织入
实现AOP
什么是AOP
@Component //注册所有bean@Controller //注册控制层的bean@Service //注册服务层的bean@Repository //注册dao层的bean
bean的注册
@Autowired 作用于 构造方法、字段、方法,常用于成员变量字段之上。@Autowired + @Qualifier 注入,指定 bean 的名称@Resource JDK 自带注解注入,可以指定 bean 的名称和类型等
bean的注入
注解
默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题
Spring不保证bean的线程安全
spring中的bean是线程安全的吗?
singleton
prototype
request
session
application
bean的作用域?
springmvc运行流程
SpringMvc的运行流程
@RequestMapping 是一个注解,用来标识 http 请求地址与 Controller 类的方法之间的映射。
@RequestMapping的作用是什么?
它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
@Autowired的作用是什么?
spring boot 基于 spring 框架的快速开发整合包。内置了tomcat服务器,直接可以打包成jar包就能独立运行
优点:编码配置部署变得简单
什么是spring boot?为什么要用?
Spring框架
第一范式:列不可再分
第二范式:行可以区分,主键约束
第三范式:表的非主属性不能依赖其他的非主属性,外键约束
数据库三范式
mysql常用引擎包括:MYISAM、Innodb、Memory、MERGE
MyISAM不支持事务,InnoDB支持事务
频繁执行全表count
对数据库增删改频率不高、频繁进行查询操作
没有事务
MyISAM支持的场景:
数据增删改频繁的操作
可靠性要求比较高、支持事务
InnoDB支持的场景
说说InnoDB与MyISAM的区别
数据库锁的分类
原子性
一致性
隔离性
持久性
隔离级别
事务隔离级别下的并发问题
数据库事务的四大特性(ACID)
脏读:A在读取一行数据后,B对这一行数据进行了更新,并回滚操作,导致A读取的数据时脏数据
幻读:A在对多行数据读取时,此时B更新了一些数据,导致A发现了一些原本不存在的数据,就像发生幻觉一样
不可重复读:A在重复读取一行数据时,B更新了这一行数据,导致A读取的数据前后不一致
脏读、幻读、不可重复读
左连接(left join):返回包括左表中的所有记录和右表中连接字段相等的记录。右连接(right join):返回包括右表中的所有记录和左表中连接字段相等的记录。内连接(inner join):只返回两个表中连接字段相等的记录。全外连接(full join):返回左右表中连接字段相等的记录和剩余所有记录。
左连接、右连接、内连接和全外连接的区别
MySQL
Redis是一个开源的保存键值对、基于内存、支持多种数据结构的存储系统,可以作为数据库、缓存。
介绍一下Redis
hash
string
list
set
sorted set
支持五种数据类型
Redis支持哪些数据类型?
1 性能极高,能到10万次/s的读写速度
2 支持数据的持久化,对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上
3 支持丰富的数据类型
4 支持数据的备份,快速的主从复制
Redis有哪些优缺点?
1 基于内存的,数据读写快
2 避免线程切换浪费资源
3 基于非阻塞IO,多路复用
4 使用了高性能数据结构,如 Hash
Redis使用单线程模型为什么性能依然很好?
Strings:一个 String 类型的 value 最大可以存储512MLists:元素个数最多为 2^32-1 个,即 4294967295 个Sets:元素个数最多为 2^32-1 个,即 4294967295 个Hashes:键值对个数最多为 2^32-1 个,即 4294967295 个Sorted sets类型:同 Sets
Redis各数据类型最大容量是多少?
数据集快照的方式半持久化模式,记录 redis 数据库的所有键值对
RDB
指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储,保存为 aof 文件
AOF
Redis持久化机制有哪些
设置键过期时间是,同时设置一个定时器,到了过期时间就进行删除操作
定时删除
不主动删除过期键,只有访问到键时,检查是否过期并进行删除
惰性删除
Redis过期键的删除策略有哪些?
会话缓存
全页缓存等
Redis有哪些适用场景?
解决策略:加锁
缓存雪崩:缓存同一时间大面积失效,大量的访问到数据库而崩掉
解决:不设置这个key的过期时间
缓存击穿:一个热点key突然失效,导致大量请求访问到数据库
解决:设置布隆过滤器
缓存穿透:缓存、数据库中没有这个key,导致在缓存找不到又去数据库查询,并返回空
Redis的缓存雪崩,缓存击穿、缓存穿透
Redis
MQ(Message Queue)消息队列,是 \"先进先出\" 的一种数据结构。
MQ 的作用:一般用来解决应用解耦,异步处理,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构。
MQ是什么?为什么使用?
MQ
MyBatis是一款持久层框架:支持自定义 SQL、存储过程以及高级映射免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作通过简单的 XML 或注解来配置和映射
介绍一下MyBatis
MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ?
使用 #{} 可以有效地防止 SQL 注入。
MyBatis 在处理 ${} 时,会直接把 ${} 替换为参数值,存在 SQL 注入的风险
#{} 和 ${} 的区别
一级缓存是SqlSession级别的缓存,默认开启的
二级缓存是NameSpace级别发缓存,多个sqlsession共享的,使用时需要在mapper.xml文件里用cache标签开启
访问顺序是:二级缓存→一级缓存→数据库
mybatis的一级缓存二级缓存
MyBatis
1 设置数据库操作权限
2 使用正则判断
3 对特殊字符进行转义处理
如何避免sql注入?
安全
由虚拟机栈
堆
方法区
本地方法栈
JVM虚拟机结构
引用计数法:设置一个计数器,一个对象被引用就加一,取消引用就减一,当引用数为零时则该对象没有存活;但是会出现循环引用,A引用B,B引用A且两者引用都不为零,导致无法判断是否存活;
用GC roots 到某一对象的路径,若可达就存活;
可达性分析
JVM判断如何对象是否存活?
在新生代-复制算法
在老年代-标记整理算法
GC分代收集
强引用:在程序内存不足(OOM)的时候也不会被回收
软引用:在程序内存不足时会被回收;需要SoftReference类来实现
弱引用:比软引用更弱,垃圾回收机制一运行就被回收;需要使用Weak Reference类来实现
虚引用:主要作用是跟踪对象被垃圾回收的状态
Java中的四种引用
在读写数据中会发生阻塞现象,若数据处于未就绪状态,用户线程继续处于阻塞状态,用户线程交出CPU
阻塞IO模型
用户线程不需要等待,马上就会得到一个结果,若得到error便知道数据未准备就绪;期间线程会不断询问内核数据是否准备就绪;非阻塞IO不会交出CPU,而会一直占用CPU
非阻塞IO模型
多路复用 IO 模型
信号驱动 IO 模型
异步 IO 模型
Java I/O
1 Channel通道
2 Buffer(缓冲)
3 Selector
NIIO三大核心部分:传统 IO 基于字节流和字符流进行操作,而 NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件
JAVA NIO
五个部分:加载,验证,准备,解析,初始化
加载.class文件、验证文件中的字节流是否符合虚拟机要求、准备变量要用的内存空间、解析并初始化;
JVM 类加载机制
JVM相关面试题
有序可重复
底层使用数组
查询快,增删慢
线程不安全
ArrayList
排列有序可重复
使用数组(支持随机访问)
查询快增删慢
线程不安全,效率低
容量不够时,默认扩展一倍容量
Vcetor
有序,可重复
底层使用链表
LinkList
list集合
排列无序,不可重复
底层使用hash表实现
存取快
内部是hashmap
HashSet
无序不可重复
底层二叉树实现
排序存储
内部是TreeMap和sortedSet
TreeSet
set集合
collection
键不可重复、值可重复
底层hash表
HashMap 最多只允许一条记录的键为 null,允许多条记录的值为 null
当链表中的元素超过了 8 个以后,会将链表转换为红黑树
底层是数组+链表+红黑树
负载因子默认:0.75;可以扩容,扩容后数组大小为当前的 2 倍
HashMap
key,value都不为null
hashtable
HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过synchronized 修饰。
1. 线程是否安全:
HashMap效率相对较高,因为HashTable加了锁,线程安全问题可以导致效率下降;
2.效率:
HashMap最多允许一条键值为null,可以有多条记录值为null;Hash Table都不能为空
3. 对Null key 和Null value的支持
HashTable默认为11,扩容为2n+1
HashMap默认16,扩容为原来2倍
4.初始大小和可扩容
JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。
5 底层数据结构
HashMap 和 Hashtable 的区别
对比图
HashSet 底层就是基于 HashMap 实现的。
HashSet 和 HashMap 区别
Map
Java集合
2、继承 Thread 对象,重写 run() 方法
一、重写 Thread 类的 run() 方法
二、实现 Runnable 接口,重写 run() 方法。
三、实现 Callable 接口,使用 FutureTask 类创建线程
四、使用线程池创建、启动线程
4 种常见的创建线程的方式
线程池是创建若干个线程放在一个容器内,需要时就放到线程池的任务队列里,用完再放回去,并不会被销毁
什么是线程池?
1 降低资源消耗:避免反复的创建线程,消耗资源
2 提高响应速度:当任务需要时直接就可以允许,不需要等到创建线程
3 提高线程的可管理性:使用线程池可以进行统一的分配,调优和监控
线程池的优点:
1 running
2 shutdown
3 STOP
4 TIDYING
5 TERMINATED
线程池的5种状态
新建(New)、就绪(Runnable):调用了start()方法运行(Running):获得CPU,开始执行 run()方法阻塞(Blocked)和:放弃CPU死亡(Dead)5 种状态
线程生命周期
有关线程池的题目
作用:确保线程互斥地访问同步代码保证共享变量的修改能够及时可见有效解决重排序问题
synchronized关键字
1. ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作,与 synchronized 会被 JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用 ReentrantLock 必须在 finally 控制块中进行解锁操作。
2. ReentrantLock 相比 synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要使用 ReentrantLock。
ReentrantLock 与 synchronized
乐观锁:即一种乐观的思想,认为读多写少,线程执行前没有问题,直到遇到并发写问题才加锁
java中的悲观锁就是Synchronized
悲观锁:悲观思想,事先认为读少写多,每次认为都有可能会出现并发写问题,在修改数据时都要加上锁
自旋锁:线程一直占用CPU自旋(等待)
乐观锁、悲观锁、自旋锁
公平锁:分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁
非公平锁:JVM 按随机、就近原则分配锁的机制则称为不公平锁
公平锁与非公平锁
互斥
破坏:一次性申请所有资源
占有且等待
破坏:可以主动释放资源
不可抢占
破坏:按序申请资源
循环等待
死锁发生的条件
其他三个条件,我们可以尝试一次性申请所有的资源,破坏 \"占有且等待\" 条件 占有部分资源的线程进一步申请其他资源时,如果申请不到,主动释放它占有的资源,破坏 \"不可抢占\" 条件 按序申请资源,破坏 \"循环等待\" 条件
只需要破坏死锁条件的任意一个就可以避免死锁;互斥不可破坏!
如何避免死锁
Java锁
抢占式调度指的是每条线程执行的时间、线程的切换都由系统控制
JVM线程调度
抢占式调度
协同式调度指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样
协同式调度
Java 中用到的线程调度
FCFS:先来先服务调度算法
SJF: 短作业优先调度算法
高响应比优先调度算法
优先调度算法
系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把 CPU 分配给队首进程,并令其执行一个时间片。
时间片轮转法
进程调度算法
JAVA 多线程并发
Java面试
0 条评论
回复 删除
下一页