java实习面试题整理

java实习面试题整理

1.栈(stack)和堆(heap)的区别

栈是为函数中基本类型的变量和对象的引用变量分配内存,是由系统自动分配,获得的空间比较小,但是速度会比 较快,储存空间是连续的。
堆是为函数创建的对象分配内存,通常是使用new关键字来实现的,是人为申请开辟,获得的空间比较大,但是速 度会比较,储存空间是不连续的。

1.==和equals的区别

1)对于==,比较的是值是否相等
如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是 同一个对象,如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
例如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

1.throw和throws的区别

throw:就是自己处理一个异常,通常使用try…catch代码块捕获处理异常
throws:不对异常做任何处理而是将异常往上传,谁调用我我就抛给谁

1.cookie 和session 的区别

cookie不是很安全,它的数据是存放在客户的浏览器上,单个cookie保存的数据不能超过4K。
session比较安全,它会在一定时间内保存在服务器上,但是当访问增多,会比较占用服务器的性能,所以考虑到减 轻服务器性能方面,应当使用cookie。

1.final, finally, finalize的区别

1)final用于声明属性方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
修饰变量:该属性一定要有初始值,要么在定义时马上初始化,要么在构造器中初始化。
该变量指向基本类型后该引用为常量,不能修改。
指向对象后,对象的引用不可变,但是对象的内容可变。
修饰方法:该方法无法被子类重写,但是可以被继承。
修饰类:该类无法被继承。比如java.lang.String类就是final类。
2)finally是异常处理语句结构的一部分,表示总是执行,一定会执行。如果try里有一个return语句,会在return前执行finally中的代码。
3)finalize是Object类的方法,执行gc时会调用此方法,可以覆盖此方法提供垃圾收集时其他资源的回收,比如关闭文件等。

1.什么是多态

两个对象存在继承关系,子类重写父类的方法,然后父类的引用指向子类的对象,可以调用父类中的所有成员,不能调用子类中特有成员。

1.接口的概念与特性

概念:接口是抽象类的特殊化,是抽象方法与常量的集合,不能被实例化,但可以作为接口变量进行声明(实例化为一个具体子类),一个类可以同时实现多个接口,接口可以弥补抽象类不能多继承的缺陷。接口不允许被接口实现,但允许被接口继承。
特性:接口中的属性是常量,默认有且只能是public static final。接口中的方法默认有且只能是public abstract.

1.内部类的概念与优点

内部类的概念:内部类就是写在类或者方法中的类,他只为这个外部类所用。
内部类的优点:防止类重名,实现多继承。
内部类只能间接通过访问外部类的方法来实例化内部类。
内部类可以隐藏你不想让别人知道的操作,实现代码的封装性。
内部类可以直接使用外部类的私有和保护属性,方便实用。
内部类可以减少开发类的数量。

1.Static关键字

Static

可以用来修饰代码块,成员变量和成员方法,被 static 修饰的成员属于类,而不属于这个类的某个对象,被类中所有对象共享,可以建议通过类名调用,这些静态变量是存放在 Java 内存区域的方法区里。还有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以,被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类

1.This和Super关键字

This

This指的是当前对象本身,哪个对象调用,this就代表哪个对象。可以用来访问本类的属性,方法,构造器,也可以用来区分局部变量和全局变量,访问构造器的话只能在构造器中使用而且必须放在第一个语句。

Super

super代表父类的引用,用于访问父类的属性、方法、构造器,访问构造器的话只能也只能放在构造器的第一句,主要用于子类和父类的属性和方法同名的情况下想直接调用父类的属性方法。

1.说一下ArrayList和LinkedList的区别

1.首先,他们的底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实现的
2.由于底层数据结构不同,他们所适用的场景也不同,Arraylist更适合随机查找,LinkedList更适合删除和添加
3.另外Arraylist和LinkedList都实现了List接口,但是LinkedList还额外实现了Deque接口,所以LinkedList还可以 当做队列来使用

1.内存溢出和内存泄漏?

内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
内存溢出:指程序申请内存时,没有足够的内存供申请者使用,比如说给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用这个时候就会报内存溢出的错误。
如何防止内存溢出: 1修改JVM参数,直接增加内存2检查错误日志,查找OOM前是否有异常或错误3对代码进行走查和分析,找出会发生内存溢出的位置4使用内存查看工具,动态查看内存使用情况。(改参,检查OOM前,走查分析找溢出,内存查看工具看内存情况)
如何防止内存泄漏:1可以使用软引用或弱引用,当内存空间不足时释放这些引用所指向的对象2一定要让程序各个分支完整地执行到程序结束,然后看看某个对象是否被引用过,若没有引用过,则说明发生了内存泄漏。(软弱引用不足释放,分支执行到结束看某对象是否被引用过若没有则属于内存泄漏)

1.为什么有字节流还要用字符流

字节流在操作字符时,可能会有中文导致的乱码,如果要都转化为字符都话是比较耗时的,所以就有了字符流。
但是字符流比较适用操作文本文件,操作二进制文件的话文件很容易损坏,二进制文件(视频,音频,pdf等待)适合用字节流来操作。

1.强、软、弱、虚引用

强引用:就是指在程序中普遍存在的,Java永远不会回收这些对象,内存不足时抛出OutOfMemory错误也不会被回收。
软引用:当内存空间不足的时候,gc会回收软引用指向的对象。
弱引用:弱引用遇到GC就回收,为了解决某些地方的内存泄漏。
虚引用:在任何时候都可能被回收。

1.数组,链表,二叉树,哈希表数据结构

数组:

数组存储的数据在地址空间上是连续的,方便数据的查找,所以查找快,增删慢,插入值会整体移动,效率低.

链表:

链表存储数据在内存空间上不是连续的。其中每个节点包含两部分,一个是存储数据元素的“数据域”,另一个是存储下一个节点地址的“指针域”。插入一个数值节点,只需将插入节点,连接到链表中即可,删除效率也可以,但是查询某个具体的值,需要从头节点开始遍历,效率很低。

二叉树

由一个根节点和两棵互不相交的左子树和右子树的组成,而且每个节点最多有两个子节点,它是用一组连续的存储单元来存放二叉树的节点元素,既有链表的好处,也有数组的好处。所以它适合处理大批量的动态的数据

哈希表

1、哈希表底层数据结构是数组,哈希表不能存储基本数据类型(因为基本数据类型不能调用其hashcode()方法和equals()方法),存储的元素具有唯一性。
2、哈希表存储元素的过程是先判断要存储的元素与已有元素的hashcode是不是相同,如果不相同则会直接存储,如果相同就会继续调用equals方法判断,如果equals方法返回的是true则不能存储否则可以存储。

1.List、Set、Map集合体系结构

List:

有索引。有序可重复。ArrayList与Vector底层是数组,查询快增删慢。LinkedList底层是双向链表,查询慢增删快。ArrayList,LinkedList都是线程不安全,Vector线程安全。

Set:

无索引。无序不重复,Set实质上使用的是Map的Key存储,如果要将自定义的类存储到Set中,需要重写equals和hashCode方法。
HashSet底层是通过Hashmap来实现的,HashSet是无序不重复的,且不能排序,集合元素可以是null,但只能放入一个null
LinkedHashSet底层是链表+哈希表,查询慢增删快,它是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的顺序所以遍历的时候会按照添加时的顺序来访问。
TreeSet底层是红黑树,一般用于排序,可以使用compareTo进行排序方法来比较元素之间大小关系,然后将元素按照升序排列。

Map

Map:Key无序不重复,Value可重复。
HashMap底层是数组+链表,它根据键的HashCode值存储数据,根据键可以直接获取它的值,访问速度很快。所以在Map 中插入、删除和定位元素比较适合用hashMap。
LinkedHashMap底层是链表+哈希表,它是HashMap的一个子类,如果需要读取的顺序和插入的相同,可以用LinkedHashMap来实现。
TreeMap底层是红黑树,与TreeSet类似,取出来的是排序后的键值对。但如果是要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。

1.为什么重写了equals方法后也必须重写hashCode方法?

主要是为了减少equals比较的次数,两个对象进行比较的时候会先进行HashCode比较,不满足则不必进行equals比较了,提高了程序的效率。还有就是为了保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况。

1.Error与Exception的区别

Error表示靠程序本身难以处理的一种异常,比如内存溢出。
Exception表示程序可以预见到的能处理的异常,可以捕获且可能恢复。

1.java中什么是自动装箱与拆箱呢?

把基本数据类型转换为引用数据类型
装箱比如int变Integer,如果某个地方的参数需要填入Integer,你传int给它,它自动会生成一个Integer传过去。反之,Integer变int,就是自动拆箱。
Int转成Integer的好处
转成integer可以调用处理int型的数据方法,例如parint将string转成int类型,而且这些封装类都实现了serilizable接口,可以在网络之间进行数据传输。

1.什么是序列化和反序列化?

如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中,或者在网络传输 Java 对象,这些场景都需要用到序列化。

  • 序列化: 将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程

如果有些变量不想进行序列化,可以transient 关键字修饰。

1.java中的垃圾回收机制(GC)

垃圾回收可以有效的防止内存泄漏,Java会有一个固定的周期去清理和回收堆中已经死亡的或者长时间没有使用的对象

1.String、StringBuffer与StringBuilder的区别

1)运行速度方面:String > StringBuffer > StringBuilder。
2)因为String是不可变对象,每次拼接都会创建一个对象,非常消耗内存空间,所以String的处理速度比StringBuilder和StringBuffer慢得多,StringBuilder和StringBuffer只需要创建一个StringBuilder和StringBuffer对象,然后用append方法拼接,无论拼接多少次都只有一个对象。
3)StringBuffer与StringBuilder的区别:StringBuffer是线程安全的,StringBuilder是线程不安全的。
4)使用场景:
String适用于操作少量数据;
StringBuffer适用于多线程操作大量数据;
StringBuilder适用于单线程操作大量数据。

1.session 的工作原理

服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不 关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存 与之对应的session为之服务

1.statement和preparestatement的区别

Statement用于执行静态sql语句,在执行时,必须指定一个事先准备好的sql语句。
PrepareStatement是预编译的sql语句对象,sql语句被预编译并保存在对象中,在执行时可以为“?”动态设置参数值。

除此之外使用Statement 的话有可能会引起sql注入,就是用户输入的参数里面有可能包含了一些sql关键词比如 “or,where”等,有可能会改变sql语句的逻辑,但是preparestatement 通过占位符的形式,传入的参数会被“”包裹起 来从而避免了sql注入。

1.什么是java的反射机制?

反射机制就是在运行状态中能动态获取当前的类的所有信息,很多框架,Jdbc,Spring IOC就是使用反射机制实现的,反射机制实质上就是不需要实例化对象(不需要new出来),将你的类进行初始化,对于私有属性也能通过反射机制进行赋值,核心就是当前类的.class文件

1.反射机制的作用

可以用来写框架和一些工具类,提高程序的可扩展性

1.如何禁用java的反射机制

将默认公共的无参构造器私有化,反射机制因为找不到无参构造器,无法进行初始化,所以运行时候会报错。

1.java反射机制应用

(1)可以用来写框架,比如常用的ORM(对象关系映射:Object Relational Mapping)的框架:MyBatis
(2)可以用来写工具类,比如常用的jdbc连接驱动
(3)可以实现Spring IOC控制反转
(4)可以获取当前类的所有方法,并为其所有的私有属性进行初始化

1.什么是线程池

线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理,线程使用完毕不会销毁,而是会先存储在线程池内。

1.线程池的作用是什么

降低资源损耗,提高响应速度因为线程创建需要时间,如果每个请求都创建一个线程去处理,那服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

1.常见的线程池有哪几种?

1、newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。
2、newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newCachedThreadPool
创建一个可缓存线程池,当任务数量减少会回收空闲线程,当任务数增加时,线程池会创建新线程来处理任务
4、newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。

1.线程池常用参数

  • corePoolSize:核心线程数量
  • maximumPoolSize:线程池中可以容纳的最大线程的数量
  • keepAliveTime:非核心线程可以保留的最长的空闲时间,
  • util :就是计算这个时间的一个单位。
  • workQueue :等待队列长度
  • threadFactory : 创建线程的线程工厂。
  • handler : 是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。

1.线程池的拒绝策略

  • AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。
  • CallerRunsPolicy 策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。
  • DiscardOleddestPolicy策略: 该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。
  • DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

1.什么是乐观锁和悲观锁

乐观锁(多读)

每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新。通常适用于读取操作比较频繁的场景。
update table。
set x=x+1, version=version+1
where id=#{id} and version=#{version};

悲观锁:(多写)

每次取数据时都总会认为会有其他线程对数据进行修改,所以都会加锁,当其他线程想要访问数据时,都会被阻塞在那里,可以通过数据库来实现,都是在操作之前加锁,MySQL中可以在查询语句后通过for update加上排他锁(写锁)或者lock in share mode加上共享锁(读锁),通常用于写入操作比较频繁的场景

1.什么是CAS以及CAS中的ABA问题

什么是CAS

CAS是乐观锁的一种实现方式,CAS算法有三个操作数,内存值V,预期值A,要修改的值B,当且仅当内存值V与预期值A相等时,将内存值V修改为B,否则什么也不做。

CAS中的ABA问题

但是CAS可能存在ABA的问题,就是一个线程把数据A变成了B,然后又重新变成了A,此时另一个线程读取该数据的时候,发现A没有变化,就误认为是原来的那个A,但是此时A的一些属性或状态已经发生过变化。

ABA问题如何解决

CAS实现会使用版本号。AtomicStampedReference内部维护了对象值和版本号,在创建AtomicStampedReference对象时,需要传入初始值和初始版本号,当AtomicStampedReference设置对象值时,对象值以及状态戳都必须满足期望值,写入才会成功。

1.什么是事务

事务就是将一组sql放到一个批次中去执行,这些sql必须一起成功,如果其中有一个失败了就会出现事务回滚,什么都没有发生过的状态。
事务的四个特性:
原子性:要么都成功,要么都失败
一致性:事务前后数据完整性必须保持一致
隔离性:事务之间互不干扰
持久性:事务一旦提交成功后,对数据库的改变是永久性的

2.事务可能产生的问题

根据事务的隔离性可能会产生的问题:
脏读:一个事务读取到另一个事务未提交的数据
不可重复读:一个事务两条相同的查询语句,查询出来的结果不一样(事务执行一半数据被另一条事务修改了)
幻读:是指在一个事务内读取到别的事务插入的数据

2.说说事务的隔离级别

事务有四种隔离级别:
java实习面试题整理事务默认隔离级别是可重复读,可序列化级别的事务操作某个表的时候会导致这个表会被锁住,其他事务无法访问,只有提交了这个事务才会释放锁

2.SQL优化

  1. 避免全表扫描,使用where或order by上建立索引;
  2. 避免向客户端返回大量数据;
  3. 避免使用 !=操作符或判断NULL值,会使引擎放弃索引而使用全表扫描;

2.索引什么情况会失效(全表扫描)

1.like查询是以%开头,会导致索引失效
2.在索引列上使用mysql的内置函数,索引失效
3.对索引列运算(如,+、-、*、/),索引失效
4.索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效
5.索引字段上使用is null, is not null,可能导致索引失效

3.Spring和SpringBoot的区别

SpringBoot是一个集成了许多第三方框架的框架,它本质上就是Spring,是Spring的拓展,它取消了Spring那种XML繁琐的配置方式,改用注解的配置方式,用来提高程序开发的效率,核心是ioc(控制反转)和aop(面向切面编程)。

3.Spring中Bean的生命周期

先解析xml配置或注解配置的类,得到一个BeanDefinition,通过这个BeanDefinition反射创建Bean对象并进行属性填充,然后回调实现了Aware接口的方法,比BeanNameAware。之后会去调用BeanPostProcessor的初始化前方法,调用init初始化方法,调用BeanPostProcessor的初始化后方法,然后将创建的Bean对象放入一个Map中,这时候就可以正常业务使用bean了。Spring容器关闭时调用DisposableBean的destory()方法。

3.对于Spring中Ioc的理解

Ioc是以一种控制反转的设计思想,传统的方式假如有 a 和 b 两个对象,a 依赖于 b 那么 a 就必须先把b New出来才能使用,控制权都在自己手上 ,而注入 IOC 之后就 a对象 与b像 之间失去了直接联系,当a 对象 运行到需要b 对象 的时候,IOC 容器会主动创建一个 b对象 注入到 a对象 需要的地方。Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。它负责对象的创建和维护,将实例化的过程交给spring去完成,对象 a 获得依赖对象 b 的过程,由主动行为变为了被动行为,可以降低使用资源双方的依赖程度

3.对于Spring中Aop的理解

①概念:面向切面编程完善了Spring的依赖注入(DI),还是对面向对象编程(OOP)的补充。可以在不修改代码 的情况下,增加新的功能。AOP有日志记录、安全控制、事务处理等功能。
②AOP四个组成部分:
连接点:用来插入的方法。
切点:被插入的方法。
通知:被插入方法的内容。
切面:切点+通知。
③AOP Advice(AOP通知)分为前置通知、后置通知、异常通知、环绕通知。

Spring中常用注解:
@Bean 把自己写的类注入到容器里
@Configuration 给配置文件加的注解
@Controller @Service @Repository @Component 都是把类注入到容器里 但是有分层
@Transactional 一般是在业务逻辑层加的 让该类有事务的功能特性
@Resource 从容器里面取资源
@RequestMapping 要执行的方法或者路径
@ResponseBody 可以在方法上加 让该方法返回数据而不是页面

3.什么是springMVC

springMVC是模型视图控制器,它的本质是servlet,主要接收前台传递的参数到后台,并且将执行完的数据返回到前台
SpringMVC的工程结构一般来说分为三层,Modle层(数据访问层)、Cotroller层(处理用户发送 的请求)、View 层(页面显示层),其中Modle层分为两层:dao层、service层,MVC架构分层 的主要作用是解耦

3.springMVC的工作原理

spring中的Dispacherservlet会拦截满足规矩的请求,截取URL中最后一串代码到配置中寻找是否有满足的映射,如果有的话会寻找映射对应的类,并且执行类的代码,将代码中需要传送跳转的请求封装到modelandview中并且返回,将modelandview中视图的url进行前缀或后缀的装配后进行页面和数据的渲染后将页面返回给用户看

3.springMVC优点:

1.本质是servlet,但是相比servlet少很多代码,有利于系统的维护和扩展
2.是Spring框架的一部分,可以方便的利用Spring所提供的其他功能。

4.什么是Mybatis

是一个基于xm文件的持久层框架,它内部封装了JDBC,所以开发的时候不需要再去加载驱动,创建和释放连接只需要关注SQL语句如何去编写,可以通过标签把SQL中的动态参数进行映射生成最终的SQL语句,然后把结果映射转为Java对象返回。

4.Mybatis的优点

mybatis把所有sq语句都封装起来,让sql语句和代码分开来管理,方便去维护和拓展
,而且它提供了映射标签,支持对象和数据库的字段的关系映射,也可以使用where if 等标签来编写动态的sql。

4.Mybatis的一级缓存和二级缓存

一级缓存默认是开启的,只在一次SqlSession(会话)中有效,也就是拿到链接到关闭连接这个区间。在这个会话里面,如果有两条相同的sql语句的话,第二条sql语句会去缓存里面取数据,而不是去数据库里面取数据,除非这两条相同的sql语句中间有增删改或者手动清除缓存的操作,缓存才会失效
二级缓存也叫全局缓存,一级缓存怍用域太低了,所以逛生了二级缓存,它是基于namespace级别的缓存。一个名称空间。对应一个二级缓存。只要开启了二级缓存,在同一个Mapper下就有效所有的数据都会先放在一级缓存中;只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!二级缓存默认是关闭的,如果要启用的话就在mapper.xml 里面加个就可以了

4.#{ } 和 ${ }的区别

${ }是直接将参数参与编译,这样的话有可能会引起sql注入,比如传过来的参数里面带有where , or 等关键字有可能会改变这条sql语句的逻辑
#{ }是将参数通过 ?站位符预编译的形式,会给传过来的参数加上 ‘ ’ ,可以防止sql注入,通常都是使用这种方式

4.什么情况下必须用${}

1.当参数不需要字符串包裹起来的时候
2.当sql中表名是从参数中取的情况 (动态拼接表名的时候)
3.order by排序语句中,因为order by 后边必须跟字段名,这个字段名不能带引号,如果带引号会被识别会字符串,而不是字段

4.Mybatis一对一,一对多,多对多

一对一:assosiation标签
比如一个学生对应一个班级,需要在班级的实体类里面写入班级的对象属性,然后在resultMap标签下和result的同级目录下的assosiation标签里配置班级的属性信息。
一对多:collection标签
比如一个班级对应多个学生…
多对多:collection标签
比如一个大学生属于不同的班级,班级里又有不同的学生

4.Mybatis对比原生的JDBC有什么优势

答mybatis优点+而且它内部封装了JDBC,开发时只需要关注SQL语句,不需再花费精力手动去加载驱动,创建和释放连接。

5.什么是Redis

Redis是一个高性能的key-value存储数据库,它是免费和开源,是当下最热门的 NoSQL技术之一,也被称之为结构化数据库。

5.Redis的优点是什么

  • Redis是基于内存操作,而且它使用单线程来操作不会有上下文切换,所以非常的快-
  • 它还支持String,list,set,zet,hash等丰富的数据类型
  • Redis单条命令式保存原子性的,这确保如果多个客户端并发访问,Redis服务器能接收更新的值
  • Redis也支持事务,但是Redis的事务是没有隔离性的,只有提交才会生效,所以不会出现脏读幻读不可重复读的现象

5.为什么要使用redis而不是memcache

与Memcached相比,Redis不仅仅支持K/V类型的数据,同时还提供list,set,hash等数据结构的存储,另外Redis支持数据备份与持久化,保证数据不易丢失。所以选择Redis作为数据缓存系统。(纯kv存储,数据量非常大,并发量非常大的业务,使用mcmemcache更合适)

5.Redis为什么单线程还可以这么快

因为redis是将所有的数据全部放在内存中操作的,肯定比直接操作磁盘快,使用多线程的话CPU上下文会切换会比较耗时,所以说使用单线程去操作效率就是最高的

5.说说rdb和aof

redis有rdb和aof两种持久化的方式

rdb

rdb是一种快照的方式进行保存,的在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复的时候只需要把rdb文件放在redis启动目录就可以了,redis会把将快照文件直接读到内存里,可以在配置文件里面配置快照触发的规则。它比较适合适合大规模的数据恢复,但是每一次触发都需要一定的时间间隔,如果Redis意外宕机了,这个最后一次修改的数据就没有了。

aof

以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来, redis每一次重启都会把这些命令执行一遍存到缓存中,每一次修改都同步,文件的完整会更加好,但是如果恢复的时候数量如果比较大,修复的速度会比rdb方式慢,所以持久化是rdb方式。

5.Redis主从复制

主从复制是指将一台主机服务器的数据 ,复制到从机服务器,主机只负责写的操作,而从机只负责读的操作,主机更新的数据会同步更新给从机。因为大部分情况下都是进行读的操作的,主从复制就是用来减轻服务器的压力。

5.哨兵模式

哨兵模式是redis主从模式高可用的版本。
在主从模式下,如果主机宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源,这样就无法达到高可用,而通过哨兵模式就可以解决这一问题。哨兵启动之后会开始监控redis主机和从机是否正常运行,当主机不能正常工作时候,哨兵模式会将随机一个从机变为主机。

5.缓存穿透,缓存击穿,缓存雪崩

缓存穿透

用户想要查询一个数据,发现redis数据库没有这个数据,于是就会向向持久层数据库查询,发现也没有,当用户很多的时候,这些请求都直接向持久层数据库查询,这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方式:

  • 布隆过滤器:如果布隆过滤器判定某个 key 不存在布隆过滤器中,那么就一定不存在,如果判定某个 key 存在,那么很大可能是存在(存在一定的误判率),所以可以在缓存之前再加一个布隆过滤器,将数据库中的所有key都存储在布隆过滤器中,在查询Redis前先去布隆过滤器查询 key 是否存在,如果不存在就直接返回,不让其访问数据库,避免对持久层数据库的查询压力。
  • 缓存空值:当出现redis查不到数据都查不到数据的时候就把这个key保存到redis中,设置它的值为空,后面再出现查询这个key的请求的时候,直接返回null,就不需要再查询数据库了。但是这种处理方式如果Key值每次都是随机的,那存进Redis也没有意义,而且占用内存空间

缓存击穿

某一个热点 key,在缓存过期的一瞬间,同时有大量的请求过来,因为这个key缓存过期了,所以请求最终都会走到数据库,让数据库瞬间压力过大
解决方案:

  • 设置热点数据永不过期
  • 使用 Redis 分布式锁,在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。

缓存雪崩

大量的热点 key 设置了相同的过期时间,导在缓存在同一时刻全部失效,让数据库瞬间压力过大,引起缓存雪崩,还有一个更严重的缓存雪崩就是Redis宕机了,那所有的缓存都失效了。
解决方案:
对于普通的缓存雪崩

  • 热点数据不过期
  • 加互斥锁
  • 可以给缓存的过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效

对于redis宕机这种情况:

  • 可以使用 主从+ 哨兵,Redis集群来避免 Redis 全盘崩溃的情况

5.Redis中的事务

redis中的事务是没有隔离级别的概念,所有的命令在事务队列中并没有直接被执行,只有发起执行命令的时候才会执行!

  • multi:开启事务
  • exec:执行事务
  • discard:放弃事务

事务的两种异常

  • 编译时异常,命令错误的时候,其他命令也不会执行
  • 运行时异常,只是语法问题,但是命令没问题时,别的命令会执行(比如incr xx,但是xx并不是一个整型的)

Redis中的监视

Watch监视,能实现一个乐观锁的功能,watch监视一个key后,会有一个类似version的功能,事务执行的时候,会进行对比version,观察这个key对应的value是否发生改变,如果改变,则事务不会执行

6.Linux常见的命令有哪些

  • ls: 列出目录
  • cd:切换目录
  • pwd:显示目前的目录
  • mkdir:创建一个新的目录
  • rmdir:删除一个空的目录
  • cp: 复制文件或目录
  • rm: 移除文件或目录
  • mv: 移动文件与目录
  • cat 由第一行开始显示文件内容
  • tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写
  • nl 显示的时候,顺道输出行号!
  • more 一页一页的显示文件内容
  • less 与 more 类似,但是比 more 更好的是,他可以往前翻页!
  • head 只看头几行
  • tail 只看尾巴几行
  • vim 编辑某个文件
  • ps aux|grep xxxxxxx.jar 停止正在运行的jar包
  • netstat -nlp | grep 8082 查看某个端口运行情况(8082)
  • kill -9 30768 杀死某个正在运行的端口进程(PID 30768)
  • nohup java -jar x.jar& 不挂断运行jar包(通常用这个)
版权声明:程序员胖胖胖虎阿 发表于 2022年10月7日 上午9:16。
转载请注明:java实习面试题整理 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...