Java常见面试问题

Java常见面试问题

java基础

static的作用

修饰成员变量,成员方法

静态内部类(也相当于是类的成员)

静态代码块

1.被static修饰的成员变量或成员方法不在属于任何一个实例对象,而是被类的实例所共享

2.仅在类第一次加载使用的时候,会初始化static修饰的部分。

3.优先于对象被加载,所以即使没有创建对象,也可以通过类去访问。

static注意事项

1.静态只能访问静态的。

2.非静态可以访问非静态的,也可以访问静态的。

JDK1.8的新特性

lambda表达式,stream流

常用集合

Collection

  1. List(有索引,可重复)
  • Arraylist: 数组,默认长度101.5倍扩容
  • LinkedList: 双向链表,没有扩容机制
  • Vector: 数组(线程安全),2倍扩容
  1. Set(无索引,不可重复)
  • HashSet:基于 HashMap 实现的,HashSet的值存放于HashMap的key上,HashMap的value统一为static final PRESENT,扩容机制同HashMap。
  • LinkedHashSet:(有序)
  • TreeSet: (有序)红黑树,不能为null
  1. Queue

Map

  • HashMap:数组+链表组成的。当链表长度大于阈值(默认为8)时,将链表转化为红黑树。初始化大小是 16 ,扩容因子默认0.752倍扩容。
  • LinkedHashMap:存取有序
  • HashTable:数组+链表组成的。(线程安全),不能为null
  • TreeMap: 红黑树,不能为null

ConcurrentHashMap

位于java.util.concurrent包下,通过一个Node<K,V>[]数组来保存添加到map中的键值对,底层是数组+链表+红黑树线程安全key和value不能为null

同步机制CAS + Synchronized
  • synchronized只锁定当前链表或红黑二叉树的首节点;

  • CAS(Compare and Swap),比较交换,CAS 操作包含三个操作数,内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。

多线程场景下如何使用 List,Set?

Collections.synchronizedList()方法将其转换成线程安全的List后再使用。

Collections.synchronizedSet()方法将其转换成线程安全的Set后再使用。

线程

创建线程的方式
  • 继承 Thread 类,重写run方法。
  • 实现 Runnable 接口,重写run方法。
  • 实现 Callable 接口,重写call方法。
  • 使用 Executors 工具类创建线程池
sleep() 和 wait() 有什么区别?
  • sleep() 是 Thread线程类的静态方法,wait() 是 Object类的方法。

  • sleep() 不释放锁;wait() 释放锁。

  • wait()通常被用于线程间交互/通信,sleep 通常被用于暂停执行。

  • wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。

线程池的实现原理

ThreadPoolExecutor参数:

  • corePoolSize :核心线程数,线程数定义了最小可以同时运行的线程数量。

  • maximumPoolSize :线程池中允许存在的工作线程的最大数量

  • keepAliveTime:线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁;

  • unit :keepAliveTime 参数的时间单位。

  • workQueue:当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,任务就会被存放在队列中。

  • threadFactory:为线程池提供创建新线程的线程工厂

  • handler :线程池任务队列超过 maxinumPoolSize 之后的拒绝策略

请添加图片描述

AQS

AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中

CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node)来实现锁的分配。

JVM

JVM组成部分

  • 类加载器(Class loader):加载class文件到JVM内存的方法区。

  • 运行时数据区域(Runtime data area):JVM的内存。

  • 执行引擎(Execution engine):执行classes中的指令(即时编译器,GC)。

  • 本地接口(Native Interface):与native libraries交互,是其它编程语言交互的接口。

JVM内存的组成

  • Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;

  • Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;

  • 方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

  • 本地方法栈(Native Method Stack):本地方法栈是为虚拟机调用 Native 方法服务的;

  • 程序计数器(Program Counter Register):cpu运行指令;

GC的算法

  • 标记-清除算法标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。

  • 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。

  • 标记-整理算法标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。

  • 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

JVM调优?

数据库

事务的隔离级别

read_uncommitted:读未提交。

read_committed:读已提交,oracle默认。

repeatable_read:可重复读,mysql模式。

serializable:可串行化。

事务的隔离用来解决下面的问题:

脏读:一个事务读取到另一个事务未提交的数据。

不可重读:一个事务两次读取到的数据不一致。

幻读:一个事务读取一个查询结果集,另外一个事务修改了或删除了某些数据,导致再次读取的结果不一致。

索引

SQL优化

Spring框架

IOC和DI

IOC(控制反转),将对象的控制权交给spring容器。

@Configuration,@Bean,@Component, @Controller, @Repository, @Service

DI(依赖注入)

@Autowired,@Resource,@Qualifier

AOP

面向切面编程,

  1. @Aspect:声明切面类

  2. 切点

    @Pointcut("execution(切点表达式)")
    public void method(){
    
    }
    
    @Pointcut("@annotation(注解全限定名)")
    public void method2(){
    
    }
    
  3. 通知类型

前置@Before(“切点方法”)

后置@AfterReturning

环绕@Around:pjp.proceed()是执行被切入的方法

异常@AfterThrowing

最终@After

常用注解

@RequestMapping:将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。

Spring事务的传播行为

① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

Spring MVC的运行流程

前端控制器DispatcherServlet,收到用户请求,转发给处理器映射器HandleMapping获取Handle对象,然后前端控制器将Handle交给处理器适配器HandleAdapter执行,获取执行结果ModeAndView,再将ModeAndView交给视图解析器ViewResolver处理解析成视图,最后前端控制器渲染视图返回给用户。

SpringBoot自动配置的原理

@EnableAutoConfiguration,开启自动配置

@Configuration,声明当前类为一个配置类

@ConditionalOnClass

Spring Cloud Alibaba

在这里插入图片描述

Redis

数据类型:string,hash,list,set,zset

Redis 的持久化机制是什么?各自的优缺点?

RDB:是Redis DataBase缩写快照

RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。

AOF:Append Only File持久化

将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。

当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。

缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 设置缓存有效时间,从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  3. 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力

缓存雪崩

缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
  3. 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

Mybatis

延迟加载

  1. 延迟加载的条件:resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能

  2. 延迟加载的好处: 先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

  3. 延迟加载的实例: 如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

缓存机制

1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/> ;

3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

数据结构

排序算法

Linux系统

常用命令

chmod abc file

其中a,b,c各为一个数字,分别表示User、Group、及Other的权限。

读r=4,写w=2,执行x=1

tar -xvf file.tar # 解压 tar包
tar -xzvf file.tar.gz # 解压tar.gz
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值