Java开发工程师面试题总结(一)

1.Gc

跟可达算法、标记清除算法,标记复制算法、老年带也有gc、标记整理,老年代不常gc
在jvm中堆的分区有三块区域,青年代、老年代、永久带,永久带在jdk1.8之后就被取消了,变成元空间了,元空间功能和永久代类似。唯一到的区别是,永久代使用的是JVM的堆内存空间,而元空间使用的是物理内存。重点的话就是它的伊甸园和老年代,我们新创建的对象会先都放在伊甸园里,伊甸园里的对象到达一定的程度之后就会触发gc(跟可达算法),触发gc的时候会把没有引用指向的对象标记出来,说明这些对象就已近称为垃圾了,利用标记清除算法回收掉,会先利用标记复制算法把不是垃圾的对象放在幸存区1里面,然后直接清空伊甸园,然后我们新new的对象又会加到伊甸园里面来,有了垃圾的话还是进行上述的一系列操作,来到幸存区1的对象有会加一个年龄,如果对象年龄到了15岁之后就会加到老年代中,老年代也会进行gc,利用标记整理算法进行gc。然后会大对象会放入永久带。
大对象会放在永久带
永久代和元空间:永久代是一片连续的堆空间、两者最大的区别是元空间使用本地内存,而永久代使用的是JVM的内存,

1.GC收集器有哪些?

串行垃圾回收器(Serial Garbage Collector)

并行垃圾回收器(Parallel Garbage Collector)

并发标记扫描垃圾回收器(CMS Garbage Collector)

G1垃圾回收器(G1 Garbage Collector)

2.类加载的机制

JVM 把描述类的数据从 .class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,

类的生命周期

类的生命周期总共分为7个阶段:加载、验证、准备、解析、初始化、使用和卸载。其中验证、准备、解析三个步骤又可统称为连接。
加载、验证、准备、初始化和卸载五个步骤的顺序都是确定的,解析阶段在某些情况下有可能发生在初始化之后,这是为了支持 Java 语言的运行期绑定的特性。

2.JVM参数设置:

-Xmx:设置JVM最大可用内存为3550M。

-Xms:设置JVM初始内存为3550m。

-Xmn:设置青年代大小。

-Xss:设置每个线程的堆栈大小。

-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4

-XX:MaxPermSize=16m:设置持久代大小为16m。

2、innodb和myasam的区别

1)InnoDB支持事务,MyISAM不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了。
2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用
3)InnoDB支持外键,MyISAM不支持
4)从MySQL5.5.5以后,InnoDB是默认引擎
5)InnoDB不支持FULLTEXT类型的索引
6)InnoDB中不保存表的行数,如select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时MyISAM也需要扫描整个表
7)对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引
8)清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表
9)InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’。

2、Mysql的锁

概述

​ 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。

MySQL大致可归纳为以下3种锁:

  • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
  • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
  • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

在使用MyIsam时,我们只可以使用表级锁,而MySQL的表级锁有两种模式:

表共享锁(Table Read Lock)和表独占写锁(Table Write Lock),他们在工作时表现如下:

  • 对某一个表的读操作,不会阻塞其他用户对同一表请求,但会阻塞对同一表的写请求;
  • 对MyISAM的写操作,则会阻塞其他用户对同一表的读和写操作;
  • MyISAM表的读操作和写操作之间,以及写操作之间是串行的。

当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。

2.Mysql事务与索引

20、如何避免死锁?

  1. 加锁顺序

按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁(并对这些锁做适当的排序),但总有些时候是无法预知的。

  1. 加锁时限

另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。

3.死锁检测

每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

事务

事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。

在并发情况下,多个事务去操作同一个数据时,会发生一些问题,比如说脏读、不可重复读、幻读的等问题,我们可以设置不同的隔离级别来解决这些问题;

事务的隔离级别分为4个阶段:读未提交、读已提交(可以解决脏读)、可重复度(可以解决不可重复读)、串行化(可以解决任何问题,包括幻读,但是效率会非常低);

索引

1、普通索引

普通索引是最基本的索引,它没有任何限制,值可以为空;仅加速查询。可以通过以下几种方式来创建或

2、唯一索引

唯一索引与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。简单来说:唯一索引是加速查询 + 列值唯一(可以有null)。

3、主键索引

主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。简单来说:主键索引是加速查询 + 列值唯一(不可以有null)+ 表中只有一个。

4、组合索引

组合索引指在多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。

5、全文索引
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较。

6、聚簇索引

叶子节点存的是数据

7、非聚簇索引

叶子节点存的是地址

索引失效

  1. is null,is not null,会让索引失效,mysql的引擎是innodb,这个引擎只支持b树索引,树里不可能有null,如果是字符串判它是不是“ ”,如果是数字类型,判断它是不是0,
  2. != 也会索引失效,替换成范围查询,换成两条sql(小于0和大于0),
  3. or
  4. 左模糊也会索引失效,8前面有没有东西不知道,插件,对数据库进行分词分段查询
  5. where不要用表达式,id-2=3,
  6. 避免在where子句中进行函数操作,调方法,
  7. extends关键字代替in,判断存不存在,拿小括号里的和数据库的对比
  8. 复合索引,指一个索引可以套在很多列上,三个列同时引用这个索引,先加到最开始的这个列上,然后后面的列复制它的算法
  9. 没有意义的查询,where1=1
  10. 索引加到有意义的列,性别,男女
  11. 索引不是越多越好,索引占空间,索引上限6个,一张表里一般就三个,
  12. 尽量使用数字型字段,1,0代表男女
  13. 尽量使用varchar,可以理解成stringbuffer,char就是string
  14. 避免频繁的创建和删除表
  15. 单次给应用程序返回大量数据,分页查询数据量就变小了

3.数据库的优化

1、选取最适用的字段属性

在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任务了

2、使用连接(JOIN)来代替子查询(Sub-Queries)

3、使用联合(UNION)来代替手动创建的临时表

4、使用外键来维护数据库的关系

5、用EXplain(执行计划)来进行sql分析,有查询慢的,适合加索引的就把索引加上

6、优化的查询语句

在搜索字符型字段时,我们有时会使用LIKE关键字和通配符

但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:

索引失效

SELECT * FROM books WHERE name>="MySQL"and name<"MySQM"

4.SpringBoot启动流程

SpringApplication的run方法做了什么?

  1. 创建一个StopWatch并执行start方法,这个类主要记录任务的执行时间
  2. 配置Headless属性,Headless模式是在缺少显示屏、键盘或者鼠标时候的系统配置
  3. 在文件META-INF\spring.factories中获取SpringApplicationRunListener接口的实现类EventPublishingRunListener,主要发布SpringApplicationEvent
  4. 把输入参数转成DefaultApplicationArguments类
  5. 创建Environment并设置比如环境信息,系统熟悉,输入参数和profile信息
  6. 打印Banner信息
  7. 创建Application的上下文,根据WebApplicationTyp来创建Context类,如果非web项目则创建AnnotationConfigApplicationContext,在构造方法中初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
  8. 在文件META-INF\spring.factories中获取SpringBootExceptionReporter接口的实现类FailureAnalyzers
  9. 准备application的上下文
    1. 初始化ApplicationContextInitializer执行Initializer的contextPrepared方法,发布
    2. ApplicationContextInitializedEvent事件
    3. 如果延迟加载,在上下文添加处理器LazyInitializationBeanFactoryPostProcessor
    4. 执行加载方法,BeanDefinitionLoader.load方法,主要初始化了AnnotatedGenericBeanDefinition
    5. 执行Initializer的contextLoaded方法,发布ApplicationContextInitializedEvent事件

10.刷新上下文(后文会单独分析refresh方法),在这里真正加载bean到容器中。如果是web容器,会在onRefresh方法中创建一个Server并启动。

5.SpringBoot自动装配

自动装配选择器

SpringBoot在启动的时候,会根据META-INF包下的spring.factories

找到自动装配的类,他会把这个类加载到内存中,

这些自动装配的类有很多条件注解,

这些条件注解会根据我们引入的jar包以及我们自己注入的bean为条件完成自动装配

详细:

spring启动是依靠启动类的main方法进行启动的,在main方法中,会调用springa

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值