面试题笔记

*此文自用

JAVA基础

面试常问对比

  • 面向对象概述

  • 面向过程更注重每一个事情的步骤细节,而面向对象更注重各个参与的角色与其所需要做的事情。这样一来相对来说面向过程的设计理念效率更高,而面向对象则代码耦合程度更低。

  • 面向过程只思考程序本身的实现方法,

    面向对象是把解决的问题按照一定的规则划分为多个独立的对象,通过多个对象之间的配合来实现应用程序的功能。这样子当应用程序的功能发生变动时,只需要修改个别对象就可以了,从而使代码更容易维护

    面向对象的特点

    封装,继承和多态

  • 封装 封装就是讲对象的属性和行为封装起来,不需要让外界知道具体的实现细节。
    一般来说都是把一些对象的属性私有化,同时提供一些可以被外界访问的属性的方法

  • 继承 类的继承是指在一个现有类的基础上去构建一个新的类,子类会自动拥有父类所有可以继承的方法和属性。
    同时子类也可以对父类的方法进行重写,同时也可以声明自己的方法和属性,
    减少代码量,增加复用性

  • 多态 基于对象所属的类不同,外部对同一个方法进行调用,执行的逻辑不同 三个条件 继承 重写,父类引用指向子类对象(使用子类对象实现方法)
    在需求变动时能容易进行维护

jdk jre jvm

  • 开发用jdk,用户运行java程序使用jre,java程序运行在jvm中

2023.11增加

JVM相关内容https://blog.csdn.net/weixin_43903312/article/details/121446081

2== 和 equals() 的区别
== :
基本数据类型 比较的是"值"是否相等
引用数据类型 比较的是所指对象的地址是否相等
equals() :
基本数据类型 不能比较
引用数据类型
没有重写的话,比较的是所指对象的地址是否相等
重写了的话,如String、Date 等,比较的是所指对象的内容是否相等

1.重载和重写的区别(构造方法不能重写):
重写overwrite/重载overload
首先,重载是基于同一个类中实现的,有参无参的构造函数就是个典型的例子,它的方法名必须相同,但是参数样式必须不同,可以随意修改返回值,抛出异常与权限修饰符,重写是基于父类继承子类实现的…相对于重载来说局限性就比较大了,它的参数必须相同,返回值,抛出的异常只能相等或者更小,权限修饰符不能更宽泛。
重载作用在同一个类中,重写的作用范围在父类子类之间

在这里插入图片描述

重载的参数必须不同,重写的参数不能进行修改
重载的返回值类型可以修改,重写的无法修改,只能返回相同的类型或者子类(参数减少/不变)
重载可以修改抛出异常,重写不能抛出新的或者更大的异常(try catch)
重载可以修改访问权限,重写不能做更严格的限制(protect<public)
重写两同两小一大:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。

子类不能抛出比父类更宽泛的异常,子类方法声明不能比父类写的方法的权限更低(更小)
2.StringBuffer和StringBuilder区别:stringbuffer线程安全,stringbuilder线程不安全但是效率更高
3.解决java精度问题 使用BigDecimal(デシマル)数据类型进行精度控制(取舍规则丰富)

4.运行时异常与编译时异常:

  • 运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
    编译时异常:是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

5.jdk1.8新特性

  • 速度更快 – 红黑树 (hashmap由数组链表 改为 数组链表红黑树,hashmap长度大于8时使用红黑树结构存储/ConcurrentHashMap加入CAS算法(乐观锁),同时也有大量volatile关键字(可见,有序/不保证原子),取消锁分段机制)
  • 代码更少 – Lambda 表达式
    - 强大的Stream API – Stream 并行流,将一段内容分成多个数据块,允许不同的线程对数据块的流进行处理
  • 便于并行 – Parallel
  • 接口可以直接进行实例化(匿名内部类? )
    最大化减少空指针异常 – Optional 代表一个值存在与否,不会报空指针异常

6. 深克隆浅克隆
深克隆为在物理内存上

  • 实现Cloneable接口
  • 使用public访问修饰符重新定义clone方法。
    ~~7.接口与抽象的区别~

在这里插入图片描述

  • 接口

  • 首先,当所有的方法都是抽象方法时,我们可以将其通过接口的方式来体现,接口不能被实例化,不能有构造方法,不能有成员变量,不能包含静态方法,最重要的是其接口可以多继承。而抽象类则是比较开放,它…

    概念:接口的初步理解是一个特殊的抽象类,当抽象类中全部都是抽象方法时,可以通过接口的方式来体现。
    特点:

    1)接口不能被实例化

    2)接口只能包含方法的声明

    3)接口的成员方法包括方法,属性,索引器,事件

    4)接口中不能包含常量,字段(域),构造函数,析构函数,静态成员
    抽象关注的是事物的本质,接口关注的是其实现的方法

    抽象类和接口的区别:

    抽象类可以有构造方法,接口中不能有构造方法。 抽象类中可以有普通成员变量,接口中没有普通成员变量
    抽象类中可以包含静态方法,接口中不能包含静态方法 一个类可以实现多个接口,但只能继承一个抽象类 接口可以被多重实现,抽象类只能被单一继承
    如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。

8.notify唤醒wait()机制
9.final匿名内部类 **类无法继承,方法无法重写,变量无法修改 **
10.多态机制

static
被static修饰的类中只能含有static方法,被static修饰的方法中只能包含static变量,static变量可以被全局访问以及修改。

string(类与数组结构被final类修饰,不可修改与增长)/stringbuffer(线程安全,被syncronized修饰,适用于多线程中,效率低)/stringbuilder(线程不安全,无锁,适用于单线程中,效率高)

  • 多态分两种:

    (1) 编译时多态(设计时多态):方法重载。

    (2)
    运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。(我们平时说得多的事运行时多态,所以多态主要也是指运行时多态)

    运行时多态存在的三个必要条件:

    一、要有继承(包括接口的实现); 二、要有重写; 三、父类引用指向子类对象。

    多态的好处:

    1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。

    2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

    3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3
    所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。

    4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。

    5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

    注意:优先级从高到低:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

11.stream流方法~~

.OBJECT类
在这里插入图片描述
常见异常:
运行时:IO异常/file文件找不到异常/sql异常/timeout超时异常
编译时:NullPointerException空指针 ArrayIndexOutofBoundsException越界

MYSQL

myisam/innodb区别:
0.myisam偏向于性能快但是出事火葬场,innodb偏向于高可用,支持ACID
1.myisam索引数据分开,innodb结合
2.innodb支持事务,myisam不行
3.innodb在崩溃时比myisam更容易恢复
4.innodb支持外键,myisam不支持,而且对MyISAM表进行读操作时,它不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写操作;而对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作。
5.innodb删除表(DELETE FROM TABLE),InnoDB支持外键,不支持FULLTEXT索引,InnoDB不保存表的行数。清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表。
6.innodb支持行锁(遇到update请求时)

  • INNODB(mysql默认引擎),myisam均使用b+树索引,memory使用hash索引(Innodb同时也支持自适应hash索引,由系统选择,因为hash无法排序及范围查询)
  • 为什么b+,不hash/红黑:hash耗费内存空间(hash冲突,使用扰动函数使数据分布均匀)且不支持范围查询(只能等值),红黑树终究也是个二叉树,其数据增加其需要遍历的节点就越多,无法与多叉树比较

索引部分
1.Mysql B+Tree索引和Hash索引的区别?hash快,效率高,但是有hash碰撞,无法范围查询,b+tree效率相对低,但是支持

2.从innodb的索引结构分析,为什么索引的key长度不能太长? 太长会导致当前页可存放key数量减少,增加了索引树的页数增多,影响查询效率。

3.数据库的索引的实现 :B+TREE(树结构天生有序,直接根据根叶遍历)/HASH(通过hash算法散列分布,通过hashcode寻找)

4.复合索引遵循前缀原则:前缀索引(适用于前几个数字区分度高)是指对文本或者字符串的前几个字符建立索引,这样索引的长度更短,查询速度更快。但是当key(a,b,c)中查找a,ab,abc才生效

5.分页查询提升性能-创建覆盖索引

  • 一个常见又非常头疼的问题就是 limit 2000000,10 ,此时需要MySQL排序前2000010 记录,仅仅返回2000000,2000010 的记录,其他记录丢弃,查询排序的代价非常大 。

5.主键索引和非主键索引有什么区别?查询语句直接搜索主键只需要搜id这个棵树,查询非主键时需要先搜索非主键这棵树,然后搜索主键(回表)~~~~

6.为什么建议使用主键自增的索引?B+树叶子节点为链表,如果设定为自增的话就可以直接尾插法,不用消耗太多时间

7.主键和唯一索引的区别?

  • 1>主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;

    2>主键不允许为空值,唯一索引列允许空值;

    3>一个表只能有一个主键,但是可以有多个唯一索引;

    4>主键可以被其他表引用为外键,唯一索引列不可以;

    5>主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本

8.怎么使用索引才能提高索引的命中?

  • 1>如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)-建议使用union

    注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

    2>对于多列索引,不是使用的第一部分(第一个),则不会使用索引

    3>如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

    4>如果mysql估计使用全表扫描要比使用索引快,则不使用索引

9.索引是越多越好吗?为什么?

  • 1>合理的建立索引能够加速数据读取效率,不合理的建立索引会拖慢数据库的响应速度。

    2>索引越多,更新数据的速度越慢。

    不要在选择的栏位上放置索引,这是无意义的。应该在条件选择的语句上合理的放置索引,比如where,order by。

10.如何让 like %abc 走索引查询?

  • 我们知道如果要让 like 查询要走索引,查询字符不能以通配符(%)开始,如果要让 like %abc 也走索引,可以使用
    REVERSE() 函数来创建一个函数索引,查询脚本

11.联合索引(key(a,b,c))的作用是什么?用于多字段查询,key(a,b,c)包含key(a)、key(a,b)、key(a,b,c) 等三个索引/可以使得筛选出的数据集更精确/在查找非主键元素时不需要回表查主键,增加效率。

12.唯一索引和普通索引哪个性能更好?查询差别不大,都是在索引树查询/更新操作时唯一索引比普通索引执行慢(唯一索引需要读取数据到内存,所以更慢些)

6.脏读,幻读,不可重复读

  • 脏读(针对未提交数据):如果一个事务中对数据进行了更新,但事务还没有提交,另一个事务可以“看到”该事务没有提交的更新结果,这样造成的问题就是,如果第一个事务回滚,那么,第二个事务在此之前所“看到”的数据就是一笔脏数据。
  • 幻读(针对其他提交前后,读取数据条数的对比):幻读是指同样一笔查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。在ReadUncommitted隔离级别下,不管事务2的插入操作是否提交,事务1在插入操作之前和之后执行相同的查询,取得的结果集是不同的,所以,ReadUncommitted同样无法避免幻读的问题。
  • 不可重复读(针对其他提交前后,读取数据本身的对比):不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的,所以,ReadUncommitted也无法避免不可重复读取的问题。

7.如何解决脏读幻读重复读:使用mysql事务隔离(只有innodb支持事务隔离)
mysql默认使用可重复读+MVCC(repeatable read+mvcc版本控制)

或是这个链接

8.mysql事务隔离级别
读未提交(READ UNCOMMITTED):在读未提交隔离级别下,事务A可以读取到事务B修改过但未提交的数据。可能发生脏读、不可重复读和幻读问题,一般很少使用此隔离级别。
读已提交(READ COMMITTED):在读已提交隔离级别下,事务B只能在事务A修改过并且已提交后才能读取到事务B修改的数据。读已提交隔离级别解决了脏读的问题,但可能发生不可重复读和幻读问题,一般很少使用此隔离级别。
可重复读(REPEATABLE READ/mysql默认使用,依赖其MVCC方法(Mutil-Version Concurrency Control)):在可重复读隔离级别下,事务B只能在事务A修改过数据并提交后,自己也提交事务后,才能读取到事务B修改的数据。可重复读隔离级别解决了脏读和不可重复读的问题,但可能发生幻读问题。
可串行化(SERIALIZABLE):除了双方都读取的情况不会阻塞,其他情况全阻塞。解决所有问题,但效率低
![在这里插入图片描述](https://img-blog.csdnimg.cn/408f9412d00f43c4bd4becdb353a1173.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5pyI6YGg,size_20,color_FFFFFF,t_70,g_se,x_16

注:serializable可序列化

8.多数据表结构优化

  • 1.限定数据的范围(如不使用*号)
  • 2.读/写分离(主表改,附表读)
  • 3.垂直分区(按列分开多表)
  • 4.水平分区(保持表结构不变,按一定策略分片区(行分))-通过路由分开数据
  • 5.客户端分片/中间件分片

9.优化效率提升方法

10.事务四大特性:

  • 1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
    2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
    3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
    4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

11.having where区别
“Where” 是一个约束声明,使用Where来约束来之数据库的数据,Where是在结果返回之前起作用的,且Where中不能使用聚合函数。
“Having”是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在Having中可以使用聚合函数。
having是从前筛选的字段再筛选,而where是从数据表中的字段直接进行的筛选的。


2023.11增加
日志

SPRING

 - IOC 控制反转设计思想,无需进行多次new对象,将设计好的对象交予第三方ioc容器管控。
 - AOP面向切面编程,代码解耦,在不改变源代码的基础上加入新功能,是一种扩展性的表现(动态代理技术)
 - 

在这里插入图片描述

AOP(面向切面编程)-关联反射与动态代理模式:解耦,通过 AOP 我们可以把一些非业务逻辑的代码(比如日志记录,统计操作,认证权限,监控,设置缓存等代码)从业务中抽取出来,以非入侵的方式与原方法进行协同。这样可以使得原方法更专注于业务逻辑,代码接口会更加清晰,便于维护(相对于javaoop的静态代码和类间继承等的关联性)。不改变原来的代码逻辑的前提下对代码业务进行增强

  • Aspect:切面,只是一个概念,没有具体的接口或类与之对应,是 Join point,Advice 和 Pointcut 的一个统称。

  • Join point:连接点,指程序执行过程中的一个点,例如方法调用、异常处理等。在 Spring AOP 中,仅支持方法级别的连接点。

  • Advice:通知,即我们定义的一个切面中的横切逻辑,有“around”,“before”和“after”三种类型。在很多的 AOP
    实现框架中,Advice 通常作为一个拦截器,也可以包含许多个拦截器作为一条链路围绕着 Join point 进行处理。

  • Pointcut:切(入)点,用于匹配连接点,一个 AspectJ 中包含哪些 Join point 需要由 Pointcut 进行筛选。

  • Introduction:引介,让一个切面可以声明被通知的对象实现任何他们没有真正实现的额外的接口。例如可以让一个代理对象代理两个目标类。

  • Weaving:织入,在有了连接点、切点、通知以及切面,如何将它们应用到程序中呢?没错,就是织入,在切点的引导下,将通知逻辑插入到目标方法上,使得我们的通知逻辑在方法调用时得以执行。

  • AOP proxy:AOP 代理,指在 AOP 实现框架中实现切面协议的对象。在 Spring AOP 中有两种代理,分别是 JDK
    动态代理和 CGLIB 动态代理。

  • JDK动态代理通过反射来接收被代理的类,
    并且要求被代理的类必须实现一个接口。

  • 如果目标类没有实现接口,那么Spring AOP会选择使用 CGLIB 来动态代理目标类。 CGLIB(Code Generation
    Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。 CGLIB是通过继承 的方式做
    动态代理,因此如果某个类被标记为 final,那么它是无法使用CGLIB做动态代理的。

Target object:目标对象,就是被代理的对象。

  • 当一段代码被try catch后再发生异常时,aop的异常通知是否执行,为什么?

bean的生命周期
1.createBeanInstance() -> 实例化
2.populateBean() -> 属性赋值
3.initializeBean() -> 初始化
4.销毁 Destruction
实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。
springmvc执行流程

spring异常处理
1.使用exceptionHandler捕获异常,设置异常返回值
2.自定义异常处理类,接收返回值,显示错误页面

SPRINGBOOT

  • 核心思想:约定大于配置,仅仅规定不符合规则的那部分进行定制化,其余自动化配置。比如依赖中的starter开箱即用
    Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
  • 启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3
    个注解: @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
    @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:
    @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class
    })。 @ComponentScan:Spring组件扫描。

多线程

产生死锁的四个必要条件:

  • 互斥条件:一个资源每次只能被一个进程使用。

  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

创建线程的三个方式:

  • 1.继承thread类并重写run方法,start启动线程
    2.实现runnable接口重写该接口的run()方法,start启动线程
    3.使用callable重写call()方法

区别:
1.实现Runnable/Callable接口相比继承Thread类的优势
(1)适合多个线程进行资源共享
(2)可以避免java中单继承的限制
(3)增加程序的健壮性,代码和数据独立
(4)线程池只能放入Runable或Callable接口实现类,不能直接放入继承Thread的类

2.Callable和Runnable的区别
(1) Callable重写的是call()方法,Runnable重写的方法是run()方法
(2) call()方法执行后可以有返回值,run()方法没有返回值
(3) call()方法可以抛出异常,run()方法不可以
(4) 运行Callable任务可以拿到一个Future对象,表示异步计算的结果 。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果

3.run()和start()区别

  • 1.start启动线程,其真正的新线程将会启动,接下来重写的run方法将会在新线程上运行,但是start方法不能重复调用,run可以。
  • 2.run方法直接调用并不会开启新线程,新的程序仍然会在当前线程上顺序执行。
    在这里插入图片描述

4.sleep(),wait()区别

  • 1.sleep()方法是Thread类里面的,主要的意义就是让当前线程停止执行,让出cpu给其他的线程,但是不会释放对象锁资源以及监控的状态,当指定的时间到了之后又会自动恢复运行状态。
  • 2.wait()方法是Object类里面的,主要的意义就是让线程放弃当前的对象的锁,进入等待此对象的等待锁定池,只有针对此对象调动notify方法后本线程才能够进入对象锁定池准备获取对象锁进入运行状态。

5.线程的五大状态

6.线程与进程的区别进程是操作系统资源调度的基本单位,线程是任务的调度执行的基本单位。
一个进程可以运行于多个线程之上,而一个线程上只能运行一个进程。

7.volatile(易变化的)关键字
如果一个字段被声明为volatile,java线程内存模型确保所有线程看到这个变量的值是一致的(可见性)
保证可见性(单次操作后其他线程立即明白其被改变)、不保证原子性(不能保证单次完整操作不能被分割,如银行转账,有需求加syncronized)、禁止指令重排序(保证其程序执行有序性)
如何解决不保证原子性? 加syncronized
8.并发编程三大特性

  • 1.原子性 即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
    2.可见性 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
    3.有序性 即程序执行的顺序按照代码的先后顺序执行。

9.Threadlocal:ThreadLocal并不是一个Thread,而是Thread的局部变量

ThreadLocal归纳下来就2类用途:

  • 保存线程上下文信息,在任意需要的地方可以获取!!!
  • 线程安全的(线程局部变量,无法线程共享数据更新),避免某些情况需要考虑线程安全必须同步带来的性能损失!!!(大众用途)

1.强引用(只要其引用类型一直被引用,就不会被回收,经典案例:new对象)
2.软引用 (jvm内存吃紧时执行回收,经典案例:temp文件/缓存(cache))
3.弱引用(只能存活到下一次垃圾回收)
4.虚引用(随时可能被回收)

10.单例多例问题:

  • 通常使用单例,因为没必要每次请求都去创建对象,较为浪费内存/但在多线程并发情况下,为了防止其对象在使用时多次被修改,可牺牲性能去创建多例保证信息有效。

锁(关联多线程/mysql)
在这里插入图片描述
1.乐观锁悲观锁区别:
乐观锁在数据操作上比较乐观,认为别人不会同时修改数据,于是只会在数据更新时判断在数据操作过程中别人是否修改了数据(CAS自旋锁),检测到对方操作数据的话就不进行此次操作,否则执行操作。
悲观锁在操作数据上比较悲观,认为别人肯定会修改数据,于是操作数据时直接将数据锁住(syncronized),知道本次操作完成后才会释放锁

2.自旋锁/适应性自旋锁

  • 自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
    获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成 busy-waiting。

  • 如果物理机器有多个处理器,能够让两个或以上的线程同时并行执行,我们就可以让后面那个请求锁的线程不放弃CPU的执行时间,看看持有锁的线程是否很快就会释放锁。

    而为了让当前线程“稍等一下”,我们需让当前线程进行自旋,如果在自旋完成后前面锁定同步资源的线程已经释放了锁,那么当前线程就可以不必阻塞而是直接获取同步资源,从而避免切换线程的开销。这就是自旋锁。

  • 自旋锁在JDK1.4.2中引入,使用-XX:+UseSpinning来开启。JDK
    6中变为默认开启,并且引入了自适应的自旋锁(适应性自旋锁)。

    自适应意味着自旋的时间(次数)不再固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也是很有可能再次成功,进而它将允许自旋等待持续相对更长的时间。如果对于某个锁,自旋很少成功获得过,那在以后尝试获取这个锁时将可能省略掉自旋过程,直接阻塞线程,避免浪费处理器资源。

3.无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

  • 这四种锁是指锁的状态,专门针对synchronized的。
  • Java对象头:包括Mark Word(标记字段)、Klass Pointer(类型指针)
  • Mark Word:默认存储对象的HashCode,分代年龄和锁标志位信息。
  • Klass Point:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
  • Monitor可以理解为一个同步工具或一种同步机制,通常被描述为一个对象。每一个Java对象就有一把看不见的锁,称为内部锁或者Monitor锁。
    在这里插入图片描述
    无锁
  • 无锁没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。

偏向锁

  • 偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。

轻量级锁

  • 是指当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

重量级锁

  • 升级为重量级锁时,锁标志的状态值变为“10”,此时Mark Word中存储的是指向重量级锁的指针,此时等待锁的线程都会进入阻塞状态。

在这里插入图片描述
4. 公平锁/非公平锁

  • 公平锁是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。公平锁的优点是等待锁的线程不会饿死。缺点是整体吞吐效率相对非公平锁要低,等待队列中除第一个线程以外的所有线程都会阻塞,CPU唤醒阻塞线程的开销比非公平锁大。

    非公平锁是多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以非公平锁有可能出现后申请锁的线程先获取锁的场景。非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程。缺点是处于等待队列中的线程可能会饿死,或者等很久才会获得锁。

5.可重入锁 VS 非可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。

6.独享锁 VS 共享锁(关联mysql)

  • 独享锁也叫排他锁,是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排它锁后,则其他线程不能再对A加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。JDK中的synchronized和JUC中Lock的实现类就是互斥锁。

    共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

    独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。

保证线程安全问题
syncronized…锁
lock/unlock
缺点:单步

锁java:偏向,自选,重量级,公平/,重复/

单例中 饿汉式无需加volatile,懒汉式 需要锁+volatile

集合

collection家族
在这里插入图片描述
Set,List, Map各自实现类的比较
为什么map不在collection内

  • map为k,v结构,而collection是数据集,根据接口分离原则(客户端不应该依赖它所不需要的接口),接口必须分开,无法继承(无数据结构特征)

名词构成:底层数据结构+本身数据结构,如treeset为红黑树底层,本身set/hashset为hashmap底层,本身set/hashmap为数组链表红黑树底层,map本身数据结构。

  • 如何遍历集合
扩容机制:
	HashMap:初始容量:16 扩容因子0.75(例:当数据大于等于16*0.75=12时触发) 触发后old*2
	HashSet:初始容量:16 扩容因子0.75 触发后old*2
	Hashtable:初始容量:capacity(11).扩容因子0.75 触发后old*2+1

	ArrayList 初始容量 10(插入数据前为0) 超出容量后新容量为原容量的1.5倍取整(低位取)
	vector 初始容量:10 超出容量则old*2
	CopyOnWriterArrayList 插多少扩多少

	stringBuffer 初始容量:16 扩容机制 大于原数组时old*2+2 如果还是溢出则扩到为整型最大值
	stringBuilder 初始容量:16 机制同StringBuffer

set(集合)
在这里插入图片描述
根据equals方法判断其元素是否相同


 - 1.不包含相同的元素,因为数据构成为<k,v>,hashset无序,treeset有序,linkedHashset有序
   2.三者均线程不安全,但可以加入Collection.syncronizedSet()进行加锁实现/CopyonwriteArraySet构造。

  • 如何使treeset有序?其插入数据时自动调用conpareable的实现compareTo方法进行对比,之后插入其数据
  • 如何使treeset不重复?其插入时自动调用Comparetor.compare(自定义)/Comparable.compareTo(自然)方法进行对比,之后根据返回值决定是否插入数据
  • hashset不重复:hashcode与equals共同判断

MAP(映射)
在这里插入图片描述

hashmap treemap linkedhashmap线程不安全,hashtable(全syn),Concurrenthashmap(cas+syn)安全
hashmap hashtable concurrentHashmap无序  treemap linkedhashmap有序
注:hashmap底层数组链表红黑树(1.8)          ↑紅黑樹    ↑双向链表
如何转变为线程安全:Collection.syncronizedMap

hashmap迭代器

hashmap部分面试题
1.为什么hashtable线程安全:方法全体加入了syncronized(同步)关键字(但由于效率太低,1.5后被ConcurrentHashMap/并行hashmap代替,其使用volatile关键字进行效率增强)
2.相对于hashtable的读写线程安全,其hashmap不加syncronized,所以不安全
3.为什么ConcurrentHashMap线程安全+速度大于hashtable

  • ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的HashTable,它们有自己的锁(分段锁)。只要多个修改操作发生在不同的段上,它们就可以并发进行。把一个整体分成了16个段(Segment.也就是最高支持16个线程的并发修改操作。这也是在重线程场景时减小锁的粒度从而降低锁竞争的一种方案。
    并且代码中大多共享变量使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好,并且可以解决重排序问题。

hashmap(1.8加入红黑树)内部结构转换机制:

  • 当链表长度大于8并且数组长度大于64时,才会转换为红黑树。
    如果链表长度大于8,但是数组长度小于64时,还是会进行扩容操作,不会转换为红黑树。因为数组的长度较小,应该尽量避开红黑树。因为红黑树需要进行左旋,右旋,变色操作来保持平衡,
    所以当数组长度小于64,使用数组加链表比使用红黑树查询速度要更快、效率要更高。

LIST列表
list部分面试题

vector线程安全,arraylist/linkedlist 线程不安全
linkedlist,arraylist,vector有序(list本身就有序)
修改为线程安全:调用Collection.synchronizedList();

1.vector线程安全,是由于方法加入了syncronized关键字

sycronized锁

  • arraylist扩容分析1.8jdk:(无参)初始化时为长度默认为0,第一次插入扩10,超出扩15,22
  • 而在之前JDK1,6中,无参数构造器代码是初始长度为10。

在这里插入图片描述

LINUX常用指令

1、ls命令
就是 list 的缩写,通过 ls 命令不仅可以查看 linux 文件夹包含的文件,而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息等等。
2、cd 命令
cd(changeDirectory) ,切换当前目录至 dirName。
3、pwd 命令
pwd(print workspace directory) 命令用于查看当前工作目录路径。
4、mkdir 命令
mkdir (make directory)命令用于创建文件夹。
5、rm 命令
remove删除一个目录中的一个或多个文件或目录,如果没有使用 -r 选项,则 rm 不会删除目录。如果使用 rm 来删除文件,通常仍可以将该文件恢复原状。
6、rmdir 命令
remove directory从一个目录中删除一个或多个子目录项,删除某目录时也必须具有对其父目录的写权限。
7、mv 命令
move 移动文件或修改文件名,根据第二参数类型(如目录,则移动文件;如为文件则重命令该文件)。
8、cp 命令
copy 将源文件复制至目标文件,或将多个源文件复制至目标目录。
9、cat 命令
一次显示整个文件:,从键盘创建一个文件:,将几个文件合并为一个文件:
10、more 命令
功能类似于 cat, more 会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示。
11、less 命令
less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件。
12、head 命令
head 用来显示档案的开头至标准输出中,默认 head 命令打印其相应文件的开头 10 行。
13、tail 命令
用于显示指定文件末尾内容,不指定文件时,作为输入信息进行处理。常用查看日志文件。
14 文件查找
which 查看可执行文件的位置。
whereis 查看文件的位置。
locate 配合数据库查看文件位置。
find 实际搜寻硬盘查询文件名称。
18、chmod 命令
用于改变 linux 系统文件或目录的访问
19、tar 命令
用来压缩和解压文件。tar 本身不具有压缩功能,只具有打包功能,有关压缩及解压是调用其它的功能来完成。权限。用它控制文件或目录的访问权限。
20、chown 命令
chown 将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户 ID;组可以是组名或者组 ID;文件是以空格分开的要改变权限的文件列表,支持通配符。
26、grep 命令
强大的文本搜索命令,grep(Global Regular Expression Print) 全局正则表达式搜索。
21.date
显示或设定系统时间
22.wc
计算文件字节,字,行数
23.ps
(process status查看当前进程运行状态 top查看动态
24.kill
杀死进程
25.free
显示占用情况
26.make
编译源码

项目相关

新闻站:用户可以访问新闻页面浏览其时事信息,同时也可以查看当前的最新新闻与最热新闻,最新新闻是通过查询数据库的发布时间以倒序排列显示,最热新闻是通过定义的一个点击量属性进行倒序排列显示的,同时在新闻浏览页还使用了分页插件pagehelper,用于对新闻进行分页。

在这里插入图片描述

建筑评奖:首先,参赛者可以上传自己的项目,查看自己的项目评分/管理员可以对参赛者的项目分配给对应的专家进行评审/专家则可以对管理员分配来的项目进行打分,当所有专家将分数打完的时候可以在参赛者窗口看到其评审结果。其中登录验证使用了md5加密在一定程度上保证了其安全性。
日志记录(全局变量/ThreadLoacl保证线程安全/jwt存入数据库搜索),传入列表

杂项

1.redis五大基本数据类型,string,list,hash,set,zset(有序set)
2.序列化与反序列化:将对象转换为字节流便于网络传输。
3.springmvc
在这里插入图片描述
4.tcp保证可靠传输:超时重传,停止等待协议
5jvm内存结构
在这里插入图片描述
5,NIO(非阻塞io)/BIO/同步/异步()

  1. mybatis一二级缓存
  2. springscurity。

面试MISS掉的知识点

1.tcp和http各工作在哪一层?
tcp:传输层,http:应用层


2023.11增加
为便于理解,可以运用软考的经验来解答下
每一层执行的协议都是为相邻的上一层提供可运行的服务
可以将整个计算机想象为整个模型的组成部分
物理层(主板上的电器元件,cpu,内存等,为数据链路层提供原数据)
数据链路层(主板到网线的部分,组成数据帧以供网络层传输,将主板上所要发出去的数据进行整合数据帧,以便于上网络层进行进一步处理)
网络层(网络终端,如网卡等,比如在win网卡驱动这边就可以设置ip等参数,实现P2P的点对点网络以便于传输层进行数据交换)
传输层(脱离了物理层的网络,如无线电波等,实现P2P的数据交换途中的部分,具有拥塞控制,超时重传==TCP相关特性,以便于支持应用层各功能的实现)
应用层(使用传输层传递来的数据进行各种功能的实现,比如UDP包发送,邮件发送等)
在这里插入图片描述

2.tcp与http区别
http:超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。
tcp:
 TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,
 而HTTP是应用层协议,主要解决如何包装数据。
3.SQL中union和union all的区别
union去重,unionall不去重,将多个数据集合成为一个
4.产生死锁的四个必要条件:

  • 互斥条件:一个资源每次只能被一个进程使用。

  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
    5.springmvc常用注解
    @Controller,

    currentHashmap分段式锁


面向对象 结合面向过程,逐步开发,效率高 耦合度高,牵-动全身。而面向对象虽然…
Final/static 是一种关键字 类…方法…成员变量…
String/StringBuffer/StringBuilder 是引用数据类型 final修饰不可变/syn修饰线程安全,效率/无锁 不安全 适单线程开发
重载重写 最大区别 同一类,参数形式()不同,而重写… 同时重载的返回值修饰符异常抛出…
Equals== =基本类型,对比值 引用对比地址/equ引用对比值
接口/抽象类 抽象为abs修饰,可含抽象方法,而全是抽象方法可以用接口代替。所以抽象类中可以定义普通成员变量,任何权限修饰符的方法。而接口无实现(1.8),不静态。最重要的,单继承多继承
常用集合类型 (!单双列集合)map:hashmap,treemap,hashtable,concurrenthashmap/list:linkedlist,arraylist,vector/set:treeset,hashset
集合相关话术:底层数据结构(名字),线程安全否(效率),什么锁,应用场景(增删查询区别)
Object类方法:并发3,对比2,克隆*1

线程五态:创建线程-新建,start至就绪,获取资源到运行,遇到sleep/io/锁机制获取失败至阻塞,运行后死亡
进程线程:xx单位,1对多。
并发三特性:原子,可见,有序
事务四特性:原子,一致,隔离,持久

#KaTeX parse error: Expected 'EOF', got '#' at position 6: 区别**:#̲是占位符,预编译替换为?,是字符串拼接,会替换为变量的值,#预编译防止sql注入
索引相关:首先快搜,没有就遍历全表
Ioc:对比传统开发模式,不用一个个类开发new对象,而将类的信息交给ioc容器,当我们需要的时候让其生成。(工厂+反射(运行时操作数据))
AOP:全称,不改变
前提下增强原有的代码功能(日志,counter)动态代理模式

2024 +++++++

性能优化相关知识点-DB
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值