面试可能会问的

java基础(继承),框架注解,redies,索引(),linux日志,服务器中间件

java基础,集合,io流,,java8的新特性,框架注解,redis,设计模式,多线程,mysql优化,锁

java基础:

内部类:http://t.csdnimg.cn/lL5gv

java类 ------编译------> .class文件 ------加载------>加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),

这个对象就包含了完整的类的结构信息。类加载顺序:load->连接->初始化

类的初始化顺序

(静态变量、静态语句块)-->(普通变量、语句块)--> 构造器;

如果有父类,则顺序是:父类static方法 --> 子类static方法 --> 父类构造方法- -> 子类构造方法

懒汉和饿汉的区别

懒汉模式:在类加载的时候不被初始化,只有当调用getInstance的时候,才会去初始化这个单例。

饿汉模式:在类加载时就完成了初始化,但是加载比较慢,获取对象比较快。

饿汉模式是线程安全的,在类创建好一个静态对象提供给系统使用,懒汉模式在创建对象时不加上synchronized,会导致对象的访问不是线程安全的。

常见错误码

200 - 服务器成功返回网页

404 - 请求的网页不存在

400 - 请求错误(参数错误,url格式错误)

504 - 网关超时

请求转发和请求重定向的区别:

请求转发是服务器端的行为:

客户端发起一个请求,服务器端接收到之后,把请求转给目标服务器,再把目标地址的结果返回给客户端。

java 复制代码
@RequestMapping("/fw")
public void forward(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/index.html").forward(request, response);

请求重定向是客户端的行为:

客户端向服务器A发起请求,服务器A返回响应,客户端再向服务器B发送请求,服务器B返回响应

java 复制代码
@RequestMapping("/rt")
public void redirect(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.sendRedirect("/index.html");
}

四种作用域对象


多线程:

https://www.jianshu.com/p/2d4d6449306b

//并发编程:
//优点:通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升
							//方便进行业务拆分

//缺点:1.并发不总是能提高运行速度的(因为线程创建和上下文切换需要开销,所以不一定)
							//2.会导致很多问题:死锁、线程安全、上下文切换、内存泄漏

						//并发三要素:原子(不可分割,要么全成功要么全失败)、可见(一个改,另一个立即看到)、有序
						//出现线程安全原因:
							//1.线程切换带来的原子性问题
							//2.缓存导致的可见性问题
							//3.编译优化带来的有序性问题

							//解决:
							//1.synchronized、LOCK,或者Atomic开头的原子类解决原子性问题
							//2.synchronized、LOCK解决可见性问题

						//并行和并发有什么区别?
							并发:多个任务在一个时间段内执行,一个处理器
							并行:多个任务在一个时间点执行,多个处理器,多核处理器

						//多线程的好处和劣势
							//好处:提高CPU利用率,一个线程等待的时候,CPU可以运行其他线程
							//劣势:线程占用内存,需要解决线程之间共享资源访问时的影响

					//线程和进程的区别:
						//线程时程序执行的最小单位,进程时资源分配的最小单位
						//进程有自己的独立地址空间,多线程程序只要有一个线程死掉,整个进程就死,多进程程序一个死掉,不影响其他
					//用户线程(前台运行-main线程)和守护线程(后台运行-CG回收线程)

					//创建线程的四种方式:----1.2.3都是先定义并重写run方法,再new后,调用start()方法,其中2.3真正也是new的Tread
						//1.继承Tread类
						//2.实现Runnable接口
						//3.实现Callable接口
						//4.使用ThreadPoolExecutor工具类创建线程池(newFixedThreadPool.newCachedTreadPool.newSingleTreadPool.newScheduleTreadPool)

					//线程的run()和start()有什么区别?
						//start()用于启动线程,run()用于执行线程的运行时代码,start()只能调一次,run()可重复调

					//为什么调用start()时会执行run()?为什么不直接调run()?
						//new一个Tread,线程进入一个新建状态;调用了start()方法,会启动一个线程并进入就绪状态;当分配到时间片后就可以运行
						//start会执行线程的相应准备工作(进入就绪),然后自动执行run方法的内容

						//直接调用run,会把run当成一个main线程下的普通方法去执行,并不会创建新的线程,也不会在某个线程中执行它,不是多线程的范畴了,没意义

					//线程的生命周期:
						//新建-就绪-运行-阻塞-死亡

						新建-就绪:调用start()方法
						就绪-运行:获取到时间片,调用run()方法
						1.运行-死亡:run()执行完成,也可以使用destroy(),sleep()强制终止
						2.运行-阻塞:线程执行sleep(),suspend(),wait()
							等待阻塞:wait(),JVM将其放入等待队列
							同步阻塞:获取synchronized锁失败:
							其他阻塞:执行sleep(),suspend();
						3.运行-就绪:执行sleep()超时


					//sleep()和wait()有什么区别?
						//1.sleep不会释放锁,wait释放锁
						//2.wait()需要notify()或者notifyAll()唤醒,sleep()休眠时间到了就会继续
						//3.sleep用于暂停执行,wait用于线程间通信交互

					//notify()和notifyAll()有什么区别?
						//notify()只会唤醒一个线程:具体哪个由JVM控制
						//notifyAll()会唤醒所有线程:将所有线程移到锁池,然后竞争,成功的继续执行,失败的在池中等待锁资源释放再此竞争

					//在java中怎么保证多线程的运行安全
						//方法一:使用安全类(使用AtomicInteger原子类)
						//方法二:使用自动锁synchronized
						//方法三:使用手动锁:Lock

					//线程优先级:1-10,默认是5

					//Java垃圾回收有什么目的,什么时候开始回收?
						//垃圾回收是在内存中没有引用的对象或是超过作用域的对象进行的,识别这些不再使用的对象来释放资源
						//如果对象被置为null,不会被立即回收,而是下一次才会释放其占用的内存

					//synchronized和Lock有什么区别?
						//首先synchronized是个关键字,Lock是个java类
						//synchronized能修饰类、方法、代码块,而Lock只能代码块
						//synchronized自动获取和释放锁,Lock需要手动释放
						//但是!Lock可以知道是否获取到锁,而synchronized不能

线程池:

					//常见的4种线程池
					1.fixedThreadPool:固定大小的线程池。适应于需要控制并发线程数的场景。
					2.CacheThreadPool:缓存线程池。
					3.ScheduledThreadPool:定时任务线程池。适用于定时执行任务的场景,如:定时备份,定时统计
					4.SingleThreadPool:单线程池。适用于需要有顺序要求的场景,如:消息队列。
					
项目中应用:有一个流程提交的时候,copyca()这个mapping方法数据量过大,导致前端响应过慢。当时系统的设计就是mappling失败也不会在前端展示,在后续会有专门手动mapping的按钮。
所以我就把copyca这个方法放在了一个单线程池中。这样既可以保证copyca中的任务按照顺序执行,也可以保证前端响应快速。


						//线程池的优点?
						//1.降低资源的消耗
						//2.提高响应速度,无需等待线程创建就能执行
						//3.提高线程的可管理性,使用线程池可以进行统一的分配和监控

序列化

https://zhuanlan.zhihu.com/p/40462507

一、序列化就是把对象转化为可传输的序列

二、序列化目的:使对象可以进行跨平台传输、网络传输

(我们跨平台传输、网络传输的数据格式是字节数组,若要使对象可以进行跨平台传输、网络传输,就需要把对象转化为字节数组,但仅仅如此还不够,因为我们没有办法把字节数组转化为之前的对象了。所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。)

三、序列化方式:JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protostuff、FST(不支持跨语言)

四、序列化技术选型关键点:

1.是否支持跨语言

2.序列化速度

3.序列化大小(若要频繁序列化,数据越小越好,不占带宽、速度快)

五、java实现序列化方式:实现Serializable接口

六、常见序列化问题

1、序列化和反序列化版本号不同:失败

(private static final long serialVersionUID=2;)

2、反序列化时新增对象属性,但版本号相同:成功

3、父类实现序列化,子类不实现序列化,子类属性反序列化正常

父类不实现序列化,子类实现序列化,父类属性不能实现反序列化

//序列化:JSON.toJSONString(); 反序列化:JSON.parseObject()


数组,集合:

数组新增:长度固定,不能新增,只能覆盖。或者转换为集合;集合新增:add()

数组长度: length;集合长度:size()

数组转集合:Arrays.asList()

集合转数组:Collateration.toArray()


hashmap:

hashmap的key只能为引用类型。通常是String.不能为基本类型,因为HashMap中的key应该重写equals()和hashCode()。

底层实现:

jdk1.7:数组+链表

jdk1.8:数组+链表+红黑树。因为链表查询效率低。

数组容量》=64且链表长度大于8时,链表-》红黑树。

hashmap根据key查询的时间复杂度:

key没发生hash冲突。若发生冲突O(n)

LinkedHashMap集合是有序的

hashmap key为null时,存放在index为0的位置。


java8的新特性:

(函数式接口):https://blog.csdn.net/Vaingloryss/article/details/99699140

框架:

Mybatis:

1.#与$:http://t.csdnimg.cn/5ZCMy

2.Mybatis工作原理:http://t.csdnimg.cn/OcDCZ

3.自己理解的步骤:pom.xml(配置jar包)-》mybatis-config.xml(配置数据源,有Spring和Mybatis结合的话,配置数据源就交给Spring)-》entity类,dao层,mapper.xml(充当daoimpl),mapper.xml中的都要在mybatis-config.xml注册-》根据工作原理进行增删改查。

(创建SqlSessionFactory->通过sqlSessionFactory创建SqlSession->通过sqlSession执行sql->sqlSession将sql发送到数据库执行,将结果映射为java对象->关闭sqlSession)

Spring:

框架注解:http://t.csdnimg.cn/6eCrz

核心组件:

SpringMVC原理:

https://www.jianshu.com/p/8a20c547e245

mysql:

1.MyISAM与InnoDB区别:

InnoDB支持事务、外键、崩溃修复。而且在Mysql5.6之后,innodb也可以支持全表扫描了。

所以MyISAM最重要的优点也没了。一般默认就是InnoDB引擎。

2.防止SQL注入:使用#{}代替${},加强权限控制,设置防注入账户

3.幂等:

4.sql语句的执行流程:https://knife.blog.csdn.net/article/details/121239292

5.事务隔离级别

读未提交:读取到其他事务未提交的数据.可能会脏读/幻读/不可重复读

读已提交:读取到其他事务已提交的数据.可能会幻读/不可重复读

可重复读:开启事务,同一条件查询结果一样.可能会幻读

可序列化:事务之间完全隔离,无法读取到其他事务未提交的数据.

脏读:事务A开始,事务B修改数据但未提交,事务A读取到了脏数据.

幻读:事务A开始,事务B插入或删除数据并提交,事务A多次读取结果不一致.解决:锁表

不可重复读:事务A开始,事务B修改数据并提交,事务A多次读取结果不一致.解决:锁行

允许事务执行在更高级别上,如:可重复读可执行在读已提交上.

6.索引

创建索引

普通索引

create index 索引名 on 表名(列名(length))

唯一索引

create unique index 索引名 on 表名(列名(length))

主键索引

alter table 表名 add primary key 索引名 (列名)

复合索引

create index 索引名 on 表名(列名,列名)

全文索引(mysql8后才有)

create fulltext index 索引名 on table 表名(列名)


删除索引:

drop index 索引名 on table


索引优缺点:提高查询性能,降低修改效率.因为对数据进行增删改查操作时,还要对索引文件进行操作

建立索引的原则:查询频率高,排序频率高的字段,唯一性强的字段加索引.也不要建立太多索引.会 降低修改速率.


索引失效的情况:

1.模糊查询%放在了最前面.使用了like '%...'

2.where A or B时,其中一个不是索引

3.联合索引没有遵循最左前缀

4.对索引列进行了函数运算


order by 是否会用到索引:

1.只有一个字段,索引正常

2.有多个字段,其中某个字段不是索引,索引失效

3.有多个字段,不遵循最左前缀原则,索引失效


聚焦索引是什么,回表


7.乐观锁和悲观锁,并举例

悲观锁:就是在他操作的时候,就会把数据锁起来不允许其他人进行操作.用来解决读-写冲突,写-写冲突.

乐观锁:不锁数据,每次操作数据之前,判断一下数据是否被修改过.用来解决写-写冲突

8.sychronized和lock区别

sychronized修饰类和方法和代码块,lock只能修饰代码块

sychronized会自动获取和释放,所以不会造成死锁.lock会造成死锁

但是lock的好处是可以记录锁的状态

9.DDL/DML/DQL/DCL

DDL:

create table 表名{列名 数据类型,列名 数据类型,列名 数据类型,...}

alter table 表名 add 字段名 字段类型;

alter table 表名 drop column 字段名 字段类型;

alter table 表名 modify column 字段名 字段类型;

alter table 表名 rename column a to b;

drop table 表名-- 删除表结构和表数据,不可回滚

truncate table 表名-- 清空表数据

DML:

insert into 表名(字段名,字段名) values (值1,值2);

delete from 表名;

update 表名 set 字段名='' where;

DQL:

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...limit

DCL:

1.创建用户

create user 用户名

2.给用户授权

grant 权限1... on 数据库.对象 to 用户

3.撤销授权

revoke 权限1... on数据库.对象 from 用户

4.查看权限

show grants for 用户名;

5.删除用户

drop user 用户名;

新增外键sql:

alter table 表名 add constraint 外键名 foregin key (本表外键) REFERENCES 外表名( 外表主键)

10.慢sql查询 explain

会把查询的sql所涉及的表,以及索引,索引长度列举出来.

1.select_type 表示了查询的类型, 它的常用取值有:

SIMPLE:表示此查询不包含 UNION 查询或子查询

SUBQUERY:包含在 Select 列表中的子查询,也就是不在 FROM 子句中的子查询

DERIVED:表示包含在 From 子句中的 Select 查询

UNION:表示此查询是 UNION 的第二和随后的查询

UNION RESULT: 从 UNION 匿名临时表检索结果的 SELECT

PRIMARY, 表示此查询是最外层的查询

DEPENDENT UNION: UNION 中的第二个或后面的查询语句, DEPENDENT 意味着 Select 依赖于外层查询中发现的数据

DEPENDENT SUBQUERY: 包含在 Select 列表中的子查询, 但子查询依赖于外层查询的结果.

2.type: 通过 type 字段, 我们判断此次查询是全表扫描还是索引扫描等

ALL < index < range < ref < eq_ref < const < system < NULL

3.row:显示读取的数据行数

4.key:查询中确切使用到的索引

https://zhuanlan.zhihu.com/p/71616887#:\~:text=MySQL 提供了一个 EXPLAIN 命令%2C它可以对 SELECT 语句进行分析,获取优化器对当前查询的执行计划,以供开发人员针对相关 SQL 进行优化。,SELECT * from user_info WHERE id < 300%3B

11.drop truncate delete 区别:

drop会删除全部的表结构和表数据.

truncate 只会删除全部的表数据,不会删除表结构

delete只会删除部分数据

truncate 不可以回滚,delete可以回滚,

速度:drop>truncate >delete

释放:

drop会释放全部的表空间

truncate 表空间和索引空间会恢复为原始大小

delete不会释放表空间和索引空间

12:mysql优化:

避免全表扫描

in替换为exist, not in 替换为not exists

or->union all

避免索引失效

模糊查询%不放最前面.使用了like '%...'

联合索引遵循最左前缀匹配原则

不对索引列进行函数运算

左表驱动右表

使用分页

在项目中遇到的实际问题

如果是检验是否存在的sql 如select count(1)form a group by a.id limit 1,则不要group by ,可以提高效率


Redis:

13:分布式锁:

分布式事务

常用的高可用的解决方案:

redis缓存:

消息队列:

相关推荐
阿伟*rui28 分钟前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7895 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust