一次性注入器怎么用Java面试必知必会知识点总结

新闻资讯2026-04-21 01:02:15

                                            

    JAVA面试宝典

面试题包括以下十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVCSpring Boot/Spring CloudHibernateMybatisRabbitMQKafkaZookeeperMySqlRedisJVM

一、Java 基础

1.JDK JRE 有什么区别?

JRE Java Runtime Environment)是Java 运行时环境……它是运行编译后的Java程序所必需的一切包,包括Java

拟机(JVM)Java基础类库、Java 命令和其他基础设施。但是,它不能用于创建新程序。

JDKJava 开发工具包……功能齐全的SDKforJava。它拥有JRE所拥有的一切,还包含了编译java源码的编译器

javac,还包含了很多java程序调试和分析的工具:jconsolejvisualvm等工具软件,还包含了java程序编写所需的

文档和demo例子程序。它能够创建和编译程序,是提供给程序员使用的。

2.== equals 的区别是什么?

1、功能不同

"=="是判断两个变量或实例是不是指向同一个内存空间的值

"equals"是判断两个变量或实例所指向的内存空间的值是不是相同。

2、定义不同

"equals"JAVA中是一个方法。

"=="JAVA中只是一个运算符合

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

两个对象equals相等,则它们的hashcode必须相等,反之则不一定。两个对象==相等,则其hashcode一定相等,

反之不一定成立。

4.final java 中有什么作用?

当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行 修饰。

final写在方法上时,表示这个方法不能被重写

final写在变量上,表示是常量,值不能再次被改变

5.java 中的 Math.round(-1.5) 等于多少?

Mathround方法是四舍五入,如果参数是负数,则往大的数如,Math.round(-1.5)=-1

6.String 属于基础的数据类型吗?

String并不是基本数据类,而是一个类(class),是C++java等编程语言中的字符串,

1字符类型:byte,char 2 基本整型:short,int,long 3 浮点型:float,double 4 布尔类型:boolean”

7.java 中操作字符串都有哪些类?它们之间有什么区别?

String : final修饰,String类的方法都是返回new String。即对String对象的任何改变都不影响到原对象,对字符串的修改操作都会生成新的对象。

StringBuffffer : 对字符串的操作的方法都加了synchronized,保证线程安全。

StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改操作,可以new StringBuilder对象,调用 StringBuilder对象的appendreplacedelete等方法修改字符串。

8.String str="i" String str=new String(“i”)一样吗?

9.如何将字符串反转?

1. 利用 StringBuffffer StringBuilder reverse 成员方法: // StringBuffffer public static String reverse1(String

str) { return new StringBuilder(str).reverse().toString(); }

2. 利用 String toCharArray 方法先将字符串转化为 char 类型数组,然后将各个字符进行重新拼接:

3. 利用 String CharAt 方法取出字符串中的各个字符:

10.String 类的常用方法都有那些?

indexOf() 返回指定字符得索引

charAt() 返回指定索引处得字符

repalce() 字符串替换

trim() 去除字符串两端的空白

split() 分割字符串 返回分割后的字符串数组

getBytes() 返回字符串的byte类型数组

length() 返回字符串的长度

toLowerCase() 字符串转小写

toUpperCase() 字符串转大写

substring() 截取字符串

equals() 字符串比较

11.抽象类必须要有抽象方法吗?

抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例

化,即不能直接构造一个该类的对象。 如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译 通不过。

12.普通类和抽象类有哪些区别?

抽象类不能被实例化

抽象类可以有抽象方法,抽象方法只需申明,无需实现

含有抽象方法的类必须申明为抽象类

抽象类的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类

抽象方法不能被声明为静态

抽象方法不能用 private 修饰

抽象方法不能用 final 修饰

13.抽象类能使用 final 修饰吗?

不能,抽象类是被用于继承的,final修饰代表不可修改、不可继承的。

14.接口和抽象类有什么区别?

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口必须指向实现所有接口实现类的对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量都是是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。

同样,一个实现接口的类,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单个继承。

15.java IO 流分为几种?

Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以

一共四个):InputStreamOutputStreamReaderWriterJava中其他多种多样变化的流均是由它们派生出来的.

16.BIONIOAIO 有什么区别?

BIO(BlockingIO)是一个连接一个线程。

NIO(java non-blocking IO)是一个请求一个线程。

AIO(Asynchronous IO)是一个有效请求一个线程。

BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

17.Files的常用方法都有哪些?

Files.exists() 检测文件路径是否存在 Files.createFile()创建文件 Files.createDirectory()创建文件夹 Files.delete() 删除文件或者目录

Files.copy() 复制文件

Files.move() 移动文件

Files.size()查看文件个数

Files.read() 读取文件

Files.write()写入文件

二、容器

18.java 容器都有哪些?

List,Map,SetCollectionLinkedListArrayList ,VectorStackHashtableHashMap

WeakHashMap

数据容器主要分为了两类: Collection: 存放独立元素的序列。 Map:存放key-value型的元素对。(这对于需要利用 key查找value的程序十分的重要!) 从类体系图中可以看出,Collection定义了Collection类型数据的最基本、最共性的功能接口,而List对该接口进行了拓展。 LinkedList :其数据结构采用的是链表,此种结构的优势是删除和添加的效率很高,但随机访问元素时效率较ArrayList类低。

ArrayList:其数据结构采用的是线性表,此种结构的优势是访问和查询十分方便,但添加和删除的时候效率很低。

HashSet: Set类不允许其中存在重复的元素(集),无法添加一个重复的元素(Set中已经存在)。

HashSet利用Hash函数进行了查询效率上的优化,其contain()方法经常被使用,以用于判断相关元素是否已经被添加过。

HashMap: 提供了key-value的键值对数据存储机制,可以十分方便的通过键值查找相应的元素,而且通过Hash散列机制,查找十分的方便。

19.Collection Collections 有什么区别?

Collection 是集合的接口,其继承类又List Set

Collections 是集合的工具类,定义了许多操作集合的静态方法。是帮助类

20.ListSetMap 之间的区别是什么?

List:有序集合

Set:不重复集合,LinkedList、HashSet按照插入排序,SortedSet可排序,HashSet无序

Map:键值对集合

21.HashMap Hashtable 有什么区别?

1 HashMap不是线程安全的 hastmap是一个接口 是map接口的子接口,是将键映射到值的对象,其中键和值都是对象,并且key不能包含重复键,但value可以包含重复值。HashMap允许null keynull value

2 HashTable是线程安全的一个Collection HashMapHashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于

HashMap允许空(null)键值(key,由于非线程安全,效率上可能高于Hashtable HashMap允许将null作为一个entrykey或者value,而Hashtable不允许。 HashMapHashtablecontains方法去掉了,改成containsvaluecontainsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMapJava1.2引进的 Map interface的一个实现。 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 HashtableHashMap采 用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

22.如何决定使用 HashMap 还是 TreeMap

TreeMap<K,V> Key值是要求实现 java.lang.Comparable ,所以迭代的时候TreeMap默认是按照Key值升序排序

的;TreeMap的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)。

HashMap<K,V> Key值实现散列 hashCode() ,分布是散列的、均匀的,不支持排序;数据结构主要是桶(数组),链 表或红黑树。适用于在Map中插入、删除和定位元素。

23.说一下 HashMap 的实现原理?

HashMap使用数组加链表实现。每个数组中储存着链表。

当使用put方法储存key-value键值对时,会先调用keyhashCode方法,得到此key经特定哈希运算后的值,然后将 此值通过其他运算得到一个值,将这个值与(length-1)做或操作(&),相当于对数组长度做取余操作。最终得到一个值作为此key在数组中的索引值,然后将key-value键值对储存进去。通过这种方法将储存的不同key-value键值 对散列到数组的不同位置。

在储存的时候,如果索引位置尚无元素,那么直接储存。如果有元素,那么就调用此keyequals方法与原有的元素

Key进行比较。如果返回true,说明在这个equals定义的规则上,这两个Key相同,那么将原有的key保留,用新的

value代替原来的value。如果返回false,那么就说明这两个keyequals定义的规则下是不同元素,那么就与此链表

的下一个结点进行比较,知道最后一个结点都没有相同元素,再下一个是null的时候,就用头插法将此key-value添加

到链表上。

HashMap对重复元素的处理方法是:key不变,value覆盖。

当使用get方法获取key对应的value时,会和储存key-value时用同样的方法,得到key在数组中的索引值,如果此索

引值上没有元素,就返回null。如果此索引值上有元素,那么就拿此keyequals方法与此位置元素上的key进行比

较,如果返回true。就返回此位置元素对应的value。如果返回false,就一直按链表往下比较,如果都是返回false

那么就返回null

另外:HashMapJDK1.8之后引入红黑树结构。HashMap是线程不安全的,线程安全的是CurrentHashMap,不过

此集合在多线程下效率低。

24.说一下 HashSet 的实现原理?

首先,我们需要知道它是Set的一个实现,所以保证了当中没有重复的元素。 一方面Set中最重要的一个操作就是查找。而且通常我们会选择

HashSet使用的是散列函数,那么它当中的元素也就无序可寻。当中是允许元素为null的。

25.ArrayList LinkedList 的区别是什么?

数据结构实现: ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。随机访问效率: ArrayList LinkedList 在随机访问的时候效率要高, 因为 LinkedList 是链表的数据存储方式,所以需要移动指针从前往后依次查找。

增加和删除效率: 在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高, 因

ArrayList 增删操作要影响数组内的其他数据的下标。

综合来说: 在需要频繁读取集合中的元素时,更推荐使用ArrayList, 而在插入和删除操作较多时,更推荐使用 LinkedList

26.如何实现数组和 List 之间的转换?List转数组:toArray(arraylist.size()方法

数组转ListArraysasList(a)方法

27.ArrayList Vector 的区别是什么?

这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合 中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的 数据是允许重复的,这是与HashSet之类的集合的最大不同处,HashSet之类的集合不可以按索引号去检索其 中的元素,也不允许有重复的元素。

ArrayListVector的区别主要包括两个方面:.

1)同步性:

ArrayList的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

2)数据增长:

要增加ArrayListVector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存 储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍)。

ArrayListVector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。

28.Array ArrayList 有何区别?

ArrayJava中的数组,声明数组有三种方式 int[] a=new int[10]; int a[]=new int[10]; int a[]={1,2,3,4}; 可以看出:在定义一个数组的时候,必须指定这个数组的数据类型及数组的大小,也就是说数组中存放的元素个数固定并且类型一样

ArrayList是动态数组,也就是数组的复杂版本,它可以动态的添加和删除元素,被称为集合,集合的声明如下

ArrayList list = new ArrayList(10); ArrayList list1 = new ArrayList(); 可以看出:在不使用泛型的情况下,这个list

可以添加进不同类型的元素的,而且arraylist是可以不用指定长度的。在使用泛型时,我们就只能添加一种类型的数

据了

29. Queue poll() remove()有什么区别?

相同点:都是返回第一个元素,并在队列中删除返回的对象。

如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。

30.哪些集合类是线程安全的?

Vector:就比Arraylist多了个同步化机制(线程安全)。

Hashtable:就比Hashmap多了个线程安全。

ConcurrentHashMap:是一种高效但是线程安全的集合。

Stack:栈,也是线程安全的,继承于Vector

31.迭代器 Iterator 是什么?

首先说一下迭代器模式,它是 Java 中常用的设计模式之一。用于顺序访问集合对象的元素,无需知道集合对象的底层实现。Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。

缺点是增加新的集合类需要对应增加新的迭代器类,迭代器类与集合类成对增加。

32.Iterator 怎么使用?有什么特点?

1Iterator()要求容器返回一个IteratorIterator将准备好返回序列的第一个元素。

2)使用next()获得序列中的下一个元素

3)使用hasNext()检查序列中是否还有元素。

4)使用remove()将迭代器新近返回的元 素删除。

有什么特点:

1 Iterator遍历集合元素的过程中不允许线程对集合元素进行修改,否则会抛出

ConcurrentModifificationEception的异常。

2Iterator遍历集合元素的过程中可以通过remove方法来移除集合中的元素,删除的是上一次Iterator.next()方法返回的对象。

3Iterator必须依附于一个集合类对象而存在, Iterator本身不具有装载数据对象的功能。

4next()方法,该方法通过游标指向的形式返回Iterator下一个元素。

33.Iterator ListIterator 有什么区别?

1)所属关系,ListIterator是一个Iterator的子类型。

2)局限:只能应用于各种List类的访问。

3)优势:

Iterator只能向前移动,而ListIterator可以双向移动。

4ListIterator add() 方法,可以向 List 中添加对象,而Iterator 不能。

34.怎么确保一个集合不能被修改?

我们可以采用Collections包下的unmodififiableMap方法,通过这个方法返回的map,是不可以修改的。他会报 java.lang.UnsupportedOperationException错。

同理:Collections包也提供了对listset集合的方法。 Collections.unmodififiableList(List)

Collections.unmodififiableSet(Set)

三、多线程

35.并行和并发有什么区别?

解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。

解释二:

并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。

解释三:

并行:在一台处理器上同时处理多个任务,

并发:在多台处理器上同时处理多个任务。如hadoop分布式集群 所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

36.线程和进程的区别?

进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫轻量级进程。

线程的划分小于进程,线程是隶属于某个进程的。进程是程序的一种动态形式,是CPU,内存等资源占用的基本单位,而线程是不能占有这些资源的。

进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信比较方便。

进程在执行过程中包含比较固定的入口,执行顺序,出口,而线程的这些过程会被应用程序所控制。

37.守护线程是什么?

1、守护线程,专门用于服务其他的线程,如果其他的线程(即用户自定义线程)都执行完毕,连main线程也执行完毕,那么jvm就会退出(即停止运行)——此时,连jvm都停止运行了,守护线程当然也就停止执行了。

2、再换一种说法,如果有用户自定义线程存在的话,jvm就不会退出——此时,守护线程也不能退出,也就是它还要运行,干嘛呢,就是为了执行垃圾回收的任务啊。

38.创建线程有哪几种方式?

1,继承Thread类,重写run方法;

 2,实现Runnable接口,重写run方法,但是比继承Thread类好用,实现接口还可以继承类,避免了单继承带来的局限性;

3,使用Executor框架创建线程池。Executor框架是juc里提供的线程池

的实现。

补充线程相关的方法:

调用线程的start():启动此线程,调用相应的run()方法

Thread的常用方法:

 1.start():启动线程并执行相应的run()方法

2.run():子线程要执行的代码放入run()方法中

3.currentThread():静态的,调取当前的线程

4.getName():获取此线程的名字

5.setName():设置此线程的名字

6.yield():调用此方法的线程释放当前CPU的执行权(很可能自己再次抢到资源)  

7.join():A线程中调用B线程的join() 方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕, A线程再接着join()之后的代码执行

8.isAlive():判断当前线程是否还存活

9.sleep(long l):显式的让当前线程睡眠l毫秒 (只能捕获异常,因为父类run方法没

有抛异常)

10.线程通信(方法在Object类中):wait() notify() notifyAll()

getPriority():返回线程优先值 setPriority(int newPriority):改变线程的优先级设置线程的优先级(非绝对,只是相对几率大些)

39.说一下 runnable callable 有什么区别?

、相同点:

1. 两者都是接口;(废话)

2. 两者都可用来编写多线程程序;

3. 两者都需要调用Thread.start()启动线程

不同点:

1. 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;

2. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

40.线程有哪些状态?

线程状态有 5 种,新建,就绪,运行,阻塞,死亡

1. 线程 start 方法执行后,并不表示该线程运行了,而是进入就绪状态,意思是随时准备运行,但是真正何时运行,是由操作系统决定的,代码并不能控制,

2. 同样的,从运行状态的线程,也可能由于失去了 CPU 资源,回到就绪状态,也是由操作系统决定的。这一步中,也可以由程序主动失去 CPU 资源,只需调用 yield 方法。

3. 线程运行完毕,或者运行了一半异常了,或者主动调用线程的 stop 方法,那么就进入死亡。死亡的线程不可逆转。

4. 下面几个行为,会引起线程阻塞。

主动调用 sleep 方法。时间到了会进入就绪状态 主动调用 suspend 方法。主动调用 resume 方法,会进入就绪状态

调用了阻塞式 IO 方法。调用完成后,会进入就绪状态。 试图获取锁。成功的获取锁之后,会进入就绪状态。 线程在等待某个通知。其它线程发出通知后,会进入就绪状态

41.sleep() wait() 有什么区别?

1、同步锁的对待不同:

sleep()后,程序并不会不释放同步锁。

wait()后,程序会释放同步锁。

2、用法的不同:

sleep()可以用时间指定版来使他自动醒过来。如果时间不到你只能调用interreput()来强行打断。

wait()可以用notify()直接唤起。

42.notify() notifyAll()有什么区别?

锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法 (或者synchronized),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程A调用了某个对象的 wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到

等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

43.线程的 run() start()有什么区别?

调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法,无法达到启动多

线程的目的,相当于主线程线性执行 Thread 对象的 run() 方法。 一个线程对线的 start() 方法只能调用一次,多次调用会抛出 java.lang.IllegalThreadStateException 异常;run() 方法没有限制。

44.创建线程池有哪几种方式?

1newCachedThreadPool(),它是用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存

线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置时间超过60秒,则被终止并移除缓存;长

时间闲置时,这种线程池,不会消耗什么资源。其内部使用SynchronousQueue作为工作队列。

2newFixedThreadPoolint nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队

列,任何时候最多有nThreads个工作线程是活动的。这意味着,如果任务数量超过了活动线程数目,将在工作队列

中等待空闲线程出现;如果工作线程退出,将会有新的工作线程被创建,以补足指定数目nThreads

3newSingleThreadExecutor(),它的特点在于工作线程数目限制为1,操作一个无界的工作队列,所以它保证了所

有的任务都是被顺序执行,最多会有一个任务处于活动状态,并且不予许使用者改动线程池实例,因此可以避免改变

线程数目。

4newSingleThreadScheduledExecutor()newScheduledThreadPool(int corePoolSize),创建的是个

ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。

5newWorkStealingPool(int parallelism),这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部

会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序。

45.线程池都有哪些状态?

1. RUNNING:线程池一旦被创建,就处于 RUNNING 状态,任务数为 0,能够接收新任务,对已排队的任务进行处

理。

2. SHUTDOWN:不接收新任务,但能处理已排队的任务。调用线程池的 shutdown() 方法,线程池由 RUNNING

变为 SHUTDOWN 状态。

3. STOP:不接收新任务,不处理已排队的任务,并且会中断正在处理的任务。调用线程池的 shutdownNow() 方法,线程池由(RUNNING SHUTDOWN ) 转变为 STOP 状态。

4. TIDYING

SHUTDOWN 状态下,任务数为 0, 其他所有任务已终止,线程池会变为 TIDYING 状态,会执行 terminated()

法。线程池中的 terminated() 方法是空实现,可以重写该方法进行相应的处理。

线程池在 SHUTDOWN 状态,任务队列为空且执行中任务为空,线程池就会由 SHUTDOWN 转变为 TIDYING 状态。

线程池在 STOP 状态,线程池中执行中任务为空时,就会由 STOP 转变为 TIDYING 状态。

5. TERMINATED:线程池彻底终止。线程池在 TIDYING 状态执行完 terminated() 方法就会由 TIDYING 转变为

TERMINATED 状态。

46.线程池中 submit() execute()方法有什么区别?

submit(Callable task)submit(Runnable task, T result)submit(Runnable task)归属于ExecutorService接口。

execute(Runnable command)归属于Executor接口。ExecutorService继承了Executor

47. java 程序中怎么保证多线程的运行安全?

线程的安全性问题体现在:

原子性:一个或者多个操作在 CPU 执行的过程中不被中断的特性

可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到

有序性:程序执行的顺序按照代码的先后顺序执行

导致原因:

缓存导致的可见性问题

线程切换带来的原子性问题

编译优化带来的有序性问题解决办法:

JDK Atomic开头的原子类、synchronizedLOCK,可以解决原子性问题 synchronizedvolatileLOCK,可以解决

可见性问题 Happens-Before 规则可以解决有序性问题

48.多线程锁的升级原理是什么?

锁的级别从低到高:

无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁

锁分级别原因:

没有优化以前,synchronized是重量级锁(悲观锁),使用 wait notifynotifyAll 来切换线程状态非常消耗系统资源;

线程的挂起和唤醒间隔很短暂,这样很浪费资源,影响性能。所以 JVM synchronized 关键字进行了优化,

把锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。

无锁:没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。

偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销。偏向锁,指的就是偏向第一个加锁线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。

偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后判断锁对象是否处于被锁定状态。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;

如果线程处于活动状态,升级为轻量级锁的状态。

轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。

当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级

锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。

重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock

现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。

49.什么是死锁?

死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

50.怎么防止死锁?

尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLockReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。 尽量使用 Java. util. concurrent 并发类代替自己手写锁。 尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。 尽量减少同步的代码块。

51.ThreadLocal 是什么?有哪些使用场景?

Thread Local类是线程局部变量,是一种实现线程安全的方式。但是在管理环境下使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java应用就存在泄露大的风险

52.说一下 synchronized 底层实现原理?

可以保证方法或代码块在运行时,同一时刻只有一个方法可以进入临时界区,同时它还可以保证共享变量的内存可见性

普通同步方法,锁是当前实列对象

静态同步方法,锁是当前类的class对象

同步方法块,锁是括号里面的对象

53.synchronized volatile 的区别是什么?

volatile本质是告诉jvm当前变量寄存器中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞。

volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改和可见性

volatile不会造成线程阻塞;synchronized可能会造成线程阻塞。

volatile标记的变量不会被编译器优化;synchronized可能被编译器优化

54.synchronized Lock 有什么区别?

首先synchronizedJava内置关键字,在jvm层里面,Lock是个类;

synchronized无法判断是否获取锁的状态,lock可以判断是否获取到锁

synchronized会自动释放锁,否则容易造成线程死锁

synchronized会等待线程,Lock 锁不会等待如果尝试获取不到锁,线程可以不用一直等待就结束了

synchronized锁适合代码少量的同步问题,lock锁适合大量的代码同步问题

55.synchronized ReentrantLock 区别是什么?

一个是关键字,一个是类,更灵活的特性,可被继承可以有方法

ReentrantLock可以获取锁的等待时间设置,这样避免死锁,各种锁的信息,灵活实现多路通知

56.说一下 atomic 的原理?

当多个线程同时对该变量进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等待到执行成功

四、反射

57.什么是反射?

主要指程序可以访问,检测,修改本身状态或行为的一种能力

Java中是指,在运行环境中,对任意一个类,可以动态生成对象或者修改这个对象有的属性和方法

58.什么是 java 序列化?什么情况下需要序列化?

序列化:将 Java 对象转换成字节流的过程。

反序列化:将字节流转换成 Java 对象的过程。当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。

序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉jvm 这个类的对象可以被序列化。

59.动态代理是什么?有哪些应用?

当想要给实现某个接口的类中的方法,加一些格外的处理。比如加日志,加事务,加权限等。可以给这个类创建一个代理,这个代理并不是定义好的,是动态生成的,具有解耦,灵活,扩展性强

60.怎么实现动态代理?

Java中实现动态代理有2种方法:

  1. 使用jdk自带的动态代理,要求被代理的对象必须实现一个接口,代理类需要实现InvocationHandler接口,使用Proxy类里的方法,模拟目标类上的接口的实现类
  2. 使用cglib的动态代理,要求被代理的对象不是final的类就可以,模拟目标类上的父类来实现

五、对象拷贝

61.为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存,因此对这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆,可以用反射的方式或序列化的方式实现。

62.如何实现对象克隆?

1实现Cloneable接口并重写object类中的clone()方法

2实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

63.深拷贝和浅拷贝区别是什么?

浅拷贝只是复制了对象的引用地址,两个对象指向同一内存地址,所有修复其中的任意值,另一个值都会随之变化

深拷贝是将对象及值复制过来,两个对象修改其中任意值另一个值不会改变

六、Java Web

64.jsp servlet 有什么区别?

Jsp翻译后变成了servlet   .jsp  jsp.java   jsp.class

jsp更擅长变现页面显示,servlet更擅长逻辑控制

servlet没有内置对象,jsp的内置对象都是必须通过httpservletrequst对象,httpservletrespose对象以及

httpservlet对象得到的

jsp是一种特殊的servlet

65.jsp 有哪些内置对象?作用分别是什么?

request:封装客户请求getpost

response:封装服务器对客户端的响应

pageContext:通过对该对象获取其他对象

session:封装用户会话的对象

application:封装服务器运行环境的对象out:输出服务器响应的输出流对象

configweb应用的配置对象

pagejsp页面本身

exception:封装页面抛出异常的对象

66.说一下 jsp 4 种作用域?

page:jsp页面本身

request:封装客户请求getpost

session:会话级别

application:封装服务器运行环境的对象

67.session cookie 有什么区别?

由于HTTP协议是无状态的协议,所以服务端记录用户的状态session是保存在服务端的

cookie是保存在客户端的

68.说一下 session 的工作原理?

session是一个存在服务器上的类似于一个散列表格的文件,里面存有我们需要信息,需要用的时候取出来,类似于 大号的map,里面的键存储的是用户的sessionid,用户向服务器发送请求的时候会带上这个sessionid。就可以从中取值

69.如果客户端禁止 cookie 能实现 session 还能用吗?

不能的到session,禁用相当于失去session ,一般认为两个是独立的东西,session底层就是一个cookie

70.spring mvc struts 的区别是什么?

struts2是类级别的拦截器,struts2Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他的方式标识其所属方法了,只能设计为多例

springmvc是方法级别的拦截,在spring整合时,springmvccontroller Bean默认单列模式Singleton,所以默认对所有的请求,只会创建一个controller ,参数封装每个方法对应每个方法上的参数

71.如何避免 sql 注入?

PreparedStatement

使用正则表达式过滤传入的参数

字符串过滤

jsp页面判断代码

72.什么是 XSS 攻击,如何避免?

跨站脚本攻击,攻击者向有xss漏洞的网站中输入恶意的HTML代码,当用户浏览该网站时,这段HTML就会自动执行,类似于sql注入攻击,而xss攻击中,通过插入恶意脚本,实现对用户浏览器的控制,获取用户的一些信息。

总体思路:对输入url进行过滤,对输出进行编码。

73.什么是 CSRF 攻击,如何避免?

跨站请求伪造,攻击者伪造用户的浏览器的请求,向访问一个用户自己曾认证访问的网站发出来,使目标网站接收并误以为是用户的真是操作而执行的命令,常用于盗取账号,转账,发送虚假信息等。攻击者利用请求网站的验证漏洞。网站不能验证请求是否源于用户的真实信息。

七、异常

74.throw throws 的区别?

throw

表示方法内抛出某种异常对象 如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错

方法的定义上使用 throws 表示这个方法可能抛出某种异常 需要由方法的调用者进行异常处理

75.finalfinallyfinalize 有什么区别?

1.final : (1)、修饰符(关键字) 如果一个类被声明为final,意味着它不能再派生新的子类,不能作为父类被继承。因此一个类不能及被声明为abstract,又被声明为final的。

(2)、将final声明在方法上,方法不能被重写

(3)、final声明在变量上,表示这个变量是常量

2.finally: 在异常处理时提供finally块来执行清除操作。如果抛出一个异常,那么相匹配的catch语句就会执行,最后都会执行finally里的内容

3.finalize: 是方法名。java技术允许使用finalize()方法在垃圾收集器(GC)将对象从内存中清除之前做必要的清理工作。这个方法是在垃圾收集器里被清理对象没有被引用的情况下调用的。.

76.try-catch-finally 中哪个部分可以省略?

catch finally 语句块可以省略其中一个。

77.try-catch-finally 中,如果 catch return 了,finally 还会执行吗?

会执行,在return 前执行

78.常见的异常类有哪些?

Error,即错误,代表JVM本身的错误,处理程序运行环境方面的异常,不能通过代码处理。比如

OutOfMemoryErrorAWTError等。

Exception:即异常,程序运行时发生的,可以被java异常处理机制使用。比如IOExceptionSQLEXception

RuntimeException等等。

异常里还分为检查时异常和运行时异常:

IOException:检查时异常,必须要try-catch来处理,或者throws抛出

NullPointException:运行时异常,不处理不会引起编译错误

八、网络

79.http 响应码 301 302 代表的是什么?有什么区别?

301 redirect: 301 代表永久性转移(Permanently Moved)

302 redirect: 302 代表暂时性转移(Temporarily Moved )

301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B搜索引擎会抓取新的内容而保存旧的网址。

80.forward redirect 的区别?

1、请求方不同

redirect:客户端发起的请求

forward:服务端发起的请求

2、浏览器地址表现不同

redirect:浏览器地址显示被请求的

urlforward:浏览器地址不显示被请求的url

3、参数传递不同

redirect:重新开始一个request,原页面的request生命周期结束。

forwardforward另一个连接的时候。request变量是在其生命周期内的。另一个页面也可以使用,其实质是把目标地址include

81.简述 tcp udp的区别?

UDP 是面向无连接的通讯协议,UDP 数据包括目的端口号和源端信息。 优点:UDP 速度快、操作简单、要求系统资源较少,由于通讯不需要连接,可以实现广播发送 缺点:UDP 传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,也不重复发送,不可靠。

TCP 是面向连接的通讯协议,通过三次握手建立连接,通讯完成时四次挥手 优点:TCP 在数据传递时,有确认、窗口、重传、阻塞等控制机制,能保证数据正确性,较为可靠。 缺点:TCP 相对于 UDP 速度慢一点,要求系统资源较多。

82.tcp 为什么要三次握手,两次不行吗?为什么?

两次握手只能保证单向连接是畅通的。

只有经过第三次握手,才能确保双向都可以接收到对方的发送的数据。

83.说一下 tcp 粘包是怎么产生的?

tcp 粘包可能发生在发送端或者接收端,分别来看两端各种产生粘包的原因:

发送端粘包:发送端需要等缓冲区满才发送出去,造成粘包; 接收方粘包:接收方不及时接收缓冲区的包,造成多个包接收。

84.OSI 的七层模型都有哪些?

1、物理层协议有:EIA/TIA-232 EIA/TIA-499V.35 V.24RJ45 Ethernet 802.3

2、数据链路层协议有:Frame RelayHDLCPPP IEEE 802.3/802.2

3、网络层协议有:IPIPXAppleTalk DDP

4、传输层协议有:TCPUDPSPX

5、会话层协议有:RPCSQLNFSNetBIOSnamesAppleTalk

6、表示层协议有:TIFFGIFJPEGPICTASCIIEBCDICencryption

7、应用层协议有:FTPWWWTelnetNFSSMTPGatewaySNMP

85.get post 请求有哪些区别?

1.get是从服务器上获取数据,post是向服务器传送数据。

2.get请求时通过URL直接请求数据,数据信息可以在URL中直接看到,比如浏览器访问;post请求是放在请求头中的,用户无法直接看到。

3.get传送的数据量较小,有限制,不能大于2KB;这主要是因为它受约于URL长度的限制。p...

4.get请求因为数据参数是暴露在URL中的,所以安全性比较低,如密码不能暴露的就不能用get

86.如何实现跨域?

1jsonp 利用了 script 不受同源策略的限制 缺点:只能 get 方式,易受到 XSS攻击

2CORSCross-Origin Resource Sharing,跨域资源共享 当使用XMLHttpRequest发送请求时,如果浏览器发现违反了同源策略就会自动加上一个请求头 origin; 后端在接受到请求后确定响应后会在后端在接受到请求后确定响应后会在 Response Headers 中加入一个属性 Access-Control-Allow-Origin; 浏览器判断响应中的

Access-Control-Allow-Origin 值是否和当前的地址相同,匹配成功后才继续响应处理,否则报错 缺点:忽略

cookie,浏览器版本有一定要求

3、代理跨域请求 前端向发送请求,经过代理,请求需要的服务器资源 缺点:需要额外的代理服务器

4Html5 postMessage 方法 允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本、多窗

口、跨域消息传递 缺点:浏览器版本要求,部分浏览器要配置放开跨域限制

5、修改 document.domain 跨子域 相同主域名下的不同子域名资源,设置 document.domain 为 相同的一级

域名 缺点:同一一级域名;相同协议;相同端口

6、基于 Html5 websocket(套接字编程) 协议 websocket Html5 一种新的协议,基于该协议可以做到浏览器与服务器全

双工通信,允许跨域请求 缺点:浏览器一定版本要求,服务器需要支持 websocket 协议

7document.xxx + iframe 通过 iframe 是浏览器非同源标签,加载内容中转,传到当前页面的属性中 缺点:

页面的属性值有大小限制

87.说一下 JSONP 实现原理?

首先在客户端注册一个callback,然后把callback的名字传给服务器。此时,服务器先生成json数据,然后以javascript语法的方式,生成functionfunction名字就是传递上来I带参数jsonp。最后将json数据直接以入参的方式,放置function中,这样就生成js语法的文档,返回给客户端。客户端浏览器,解析script变迁,并执行返回javascript文档,此时数据作为参数,传入了客户端预先定义好的callback函数里。简单的说,就是利用

script标签没有跨域限制的漏洞来达到与第三方通讯的目的。

九、设计模式

88.说一下你熟悉的设计模式?

Java中一般认为有23 种设计模式, 总体来说设计模式分为三大类:

创建型模式,共五种: 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种: 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一 种: 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录 模式、状态模式、 访问者模式、中介者模式、解释器模式。

// 直接创建对象 public static Singleton instance = new Singleton(); // 私有化构造函数 private Singleton() { }

// 返回对象实例 public static Singleton getInstance() { return instance; }

89.简单工厂和抽象工厂有什么区别?

简单工厂模式 是由一个工厂对象创建产品实例,简单工厂模式的工厂类一般是使用静态方法,通过不同的参数的创建不同的对象实例 可以生产结构中的任意产品,不能增加新的产品

抽象工厂模式 提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类,生产多个系列产品 生产不同产品族的全部产品,不能新增产品,可以新增产品族

十、Spring/Spring MVC

90.为什么要使用 spring

1.方便解耦,便于开发(Spring就是一个大工厂,可以将所有对象的创建和依赖关系维护都交给spring管理)

2.spring支持aop编程(spring提供面向切面编程,可以很方便的实现对程序进行权限拦截和运行监控等功能)

3.声明式事务的支持(通过配置就完成对事务的支持,不需要手动编程)

4.方便程序的测试,spring junit4支持,可以通过注解方便的测试spring 程序

5.方便集成各种优秀的框架()

6.降低javaEE API的使用难度(Spring javaEE开发中非常难用的一些API 例如JDBC,javaMail,远程调用等,都提供了封装,是这些API应用难度大大降低)

91.解释一下什么是 aop

在业务系统中,总有一些不得不处理的事情,我们 将这些重复性的代码抽取出来,放在专门的类中, 在通过springAOP的核心对代码段进行增强处理。 在不改变原代码的基础上进行功能增强。有五种 增强方式,前置增强,后置增强,环绕增强,引介增强,异常增强。

92.解释一下什么是 ioc

iocinverse of control )控制反转:所谓控制反转就是把对象(bean)和维护对象(bean)之间的关系 的权利转移到Sqring容器中去了(ApplicationContext.xml)而程序本身不在维护了

didependency injection)依赖注入:实际上DIIOC是同一个概念,因为在ApplicationContext.xml配置文件中beanbean之间通过ref来维护的时候是相互依赖的,所以又叫做依赖注入。

93.spring 有哪些主要模块?

Spring有七大功能模块,分别是Spring CoreAOPORMDAOMVCWEBContext

1Spring Core

Core模块是Spring的核心类库,Spring的所有功能都依赖于该类库,Core主要实现IOC功能,Sprign的所有功 能都是借助IOC实现的。

2AOP AOP模块是SpringAOP库,提供了AOP(拦截器)机制,并提供常用的拦截器,供用户自定义和配置。

3ORM Spring ORM模块提供对常用的ORM框架的管理和辅助支持,Spring

持常用的Hibernateibtasjdao等框架的支持,Spring本身并不对ORM进行实现,仅对常见的ORM框架进行封装,并对其进行管理

4DAO模块 Spring 提供对JDBC的支持,对JDBC进行封装,允许JDBC使用Spring

源,并能统一管理JDBC事物,并不对JDBC进行实现。(执行sql语句)

5WEB模块 WEB模块提供对常见框架

Struts1WEBWORKStruts 2),JSF的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也 能在这些框架的前后插入拦截器。

6Context模块 Context模块提供框架式的Bean访问方式,其他程序可以通 过Context访问SpringBean资源,相当于资源注入。

7MVC模块 WEB MVC模块为Spring提供了一套轻量级

MVC实现,在Spring的开发中,我们既可以用Struts也可以用Spring自己的MVC框架,相对于StrutsSpring 自己的MVC框架更加简洁和方便。

94.spring 常用的注入方式有哪些?

构造方法注入,setter 注入,基于注解的注入

主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:

@Component:可以用于注册所有bean @Repository:主要用于注册dao层的bean @Controller:主要用于注册控 制层的bean @Service:主要用于注册服务层的bean

95.spring 中的 bean 是线程安全的吗?

容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scopeBean去研究。

96.spring 支持几种 bean 的作用域?

singleton:单例模式,在整个Spring IoC容器中,使用 singleton 定义的 bean 只有一个实例

prototype:原型模式,每次通过容器的getbean方法获取 prototype 定义的 bean 时,都产生一个新的 bean 实例

97.spring 自动装配 bean 有哪些方式?

1)在XML中进行显式配置

2)在java中进行显式配置

3)隐式的bean发现和自动装配(一般推荐使用自动装配bean的方式)

98.spring 事务实现方式有哪些?

1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()

commit()rollback()等事务管理相关的方法,这就是编程式事务管理。

2)基于 TransactionProxyFactoryBean的声明式事务管理

3)基于 @Transactional 的声明式事务管理

4)基于Aspectj AOP配置事务

99.说一下 spring 的事务隔离?

READ UNCOMMITTED(读未提交数据):允许事务读取未被其他事务提交的变更数据,会出现脏读、不可重复读和幻读问题。 READ COMMITTED(读已提交数据):只允许事务读取已经被其他事务提交的变更数据,

可避免脏读,仍会出现不可重复读和幻读问题。 REPEATABLE READ(可重复读):确保事务可以多次从一个字

段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出

现幻读问题。 SERIALIZABLE(序列化):确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止

其他事务对该表执行插入、更新和删除操作,可避免所有并发问题,但性能非常低。 Spring隔离级别

100.说一下 spring mvc 运行流程?

用户发送请求到前端控制器DispatcherServlet,之后调用HanderMapping处理器找到具体的处理器返回,再调用 HanderAdapter处理适配器,再调用具体的Controller,执行完后返回ModeandviewHanderAdapter将结果返回 给DispatcherServlet,再传给ViewResover视图解析器解析后返回ViewDispatcherServlet渲染后响应

101.spring mvc 有哪些组件?

HanderMapping处理请求,HanderAdapter适配器,ViewResolver视图解析,Contoller处理器,DispatcherServlet

102.@RequestMapping 的作用是什么?

处理请求地址映射的注解,如果用于类上,表示类中的所有响应请求方法都是以该路径作为父路径

103.@Autowired 的作用是什么?

对类成员变量、方法和构造函数进行标注,完成自动装配的工作

十一、Spring Boot/Spring Cloud

104.什么是 spring boot

springbootspring下的子项目,是spring的一站式解决方案,主要是简化spring的使用难度,降低对配置文件的要求,使开发人员跟容易上手

105.为什么要用 spring boot

1.简化spring配置文件 2.没有代码和xml文件的生成 3.内置Tomcat 4.能够独立运行 5.简化监控

106.spring boot 核心配置文件是什么?

核心配置文件有applicationbootstarp配置文件

107.spring boot 配置文件有哪几种类型?它们有什么区别?

两种,application主要作用于springboot 自动化配置文件

bootstarp:使用Spring Cloud Config注册中心时 需要在bootStarp配置文件中添加链接到配置中心的配置属性来加 载外部配置中心的配置信息。一些固定的不能被覆盖的属性。一些加密/解密的场景

108.spring boot 有哪些方式可以实现热部署?

模板引擎热部署,spring Loader热部署,JRebel热部署工具

109.jpa hibernate 有什么区别?

主要区别是jpa是一个规范,hibernate是对jap规范的实现

110.什么是 spring cloud

为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,领导

选举,分布式会话,集群状态)。

111.spring cloud 断路器的作用是什么?

当一个服务调用另一个服务由于网络原因或自身原因出现问题,调用者就会等待被调用者的响应 当更多的服务请求到这些资源导致更多的请求等待,发生连锁效应(雪崩效应)

服务的熔断(服务端),服务的降级(客户端)

112.spring cloud 的核心组件有哪些?

服务发现Netflflix Eureka,客户端负载均衡Netflflix Ribbon,断路器Netflflix Hystrix,服务网关Netflflix Zuul,分布式配 置Spring cloud config

十二、Hibernate

113.为什么要使用 hibernate

JDBC访问数据库的代码做了封装,它是基于JDBC的主流持久化框架,是一个优秀个ORM实现

使用的是Java的反射机制,而不是字节码增强程序来实现透明性

114.什么是 ORM 框架?

Object Relational Mapping

Java程序对象 关系型数据库 

对象关系映射,通过类和数据库表的映射关系,将对象持久化到数据库中

115.hibernate 中如何在控制台查看打印的 sql 语句?

只需要来在配置文源件zhidao hibernate.show_sql=true hibernate.dialect=org.hibernate.dialect.MySQLDialect

hibernate.show_sql=true

116.hibernate 有几种查询方式?

三种,即HQLQBC,以及原生的SQL

117.hibernate 实体类可以被定义为 final 吗?

可以,但是这种做法并不好,因为会使用代理模式在延迟关联的情况下提高性能,如果定义了,因为java不允许对final类进行扩展,所以就不能再使用代理了,如此就限制了提升性能的手段

118. hibernate 中使用 Integer int 做映射有什么区别?

如果数据库中对应的存储数据为null,使用int会出现类型转换异常,使用Integer则不会

119.hibernate 是如何工作的?

通过Configguration对象读取配置文件,读取并解析映射信息创建SessionFactory对象,打开session,创建

Transaction,持久化操作对对象进行CRUD操作,提交事务,关闭sessionSessionFactory对象

120.get() load()的区别?

get()被调用时会立即发出SQL语句,并且返回对象也是实际对象

Get如果查询的值不存在会返回null

load()返回的是代理对象,会使用延迟加载

load查询的值如果不存在,会报错

121.说一下 hibernate 的缓存机制?

缓存范围分三类,事务缓存,应用缓存,集群缓存,分别为session一级缓存,单SessionFactory即二级缓存, 多SessionFactory 集群缓存

122.hibernate 对象有哪些状态?

Transient 瞬时,Persistent 持久,Detached 脱管

瞬时状态如何转换为持久状态

持久状态如何变为脱管状态

123. hibernate getCurrentSession openSession 的区别是什么?

getCurrentSession创建的session会和绑定到当前线程,openSession不会。

getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,openSession必须手动关闭

124.hibernate 实体类必须要有无参构造函数吗?为什么?

要,因为hibernate框架会调用这个默认构造方法来构造实例对象。

十三、Mybatis

125.mybatis #{} ${}的区别是什么?

占位符和拼接符

126.mybatis 有几种分页方式?

数组分页,SQL分页,拦截器分页,RowBounds分页

127.RowBounds 是一次性查询全部结果吗?为什么?

如果不使用offffsetlimit,则返回该条件下的所有,如果使用则返回设置的

128.mybatis 逻辑分页和物理分页的区别是什么?

物理分页:sql语句指定,查询哪一页的数据,只会取那一页的那几条数据出来,速度上并不一定快于逻辑分页,

逻辑分页:第一次将所有的数据全部取出来放入内存中,需要使用时,取对应页的片段。速度上也并不一定快于物理分页。

物理分页总是优于逻辑分页:没有必要将属于数据库端的压力加诸到应用端来,

就算速度上存在优势,然而其它性能上的优点足以弥补这个缺点

129.mybatis 是否支持延迟加载?延迟加载的原理是什么?

支持,原理是使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,再去数据库查询

130.说一下 mybatis 的一级缓存和二级缓存?

一级缓存是Sqlsession级别的缓存,也就是同一个Sqlsession内执行两次或多次相同结果的查询语句,只会再第一次发送sql语句查询

二级缓存默认是不开启的,是Mapper级别的缓存,是多个Sqlsession之间可以共享数据

131.mybatis hibernate 的区别有哪些?

mybatishibernate不同,它不完全是一个ORM框架,因为Mybatis需要程序员自己编写sql

mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,但是灵活的前提是mybatis无法做到数据库无关性

hibernate对象/关系映射能力强,数据库无关性好

132.mybatis 有哪些执行器(Executor)?

SimpleExecutor:每次执行一个updateselect,就开启一个statment对象,用完就关闭

ReuseExecutor:执行updateselect,以sql作为key查找statment对象,存在就是用,不存在就创建,用完后不关闭

BatchExecutor:执行update,将所有sql都添加到批处理中,等待统一执行

133.mybatis 分页插件的实现原理是什么?

使用mybatis提供的插件接口,实现自定义插件,在插件拦截器方法内拦截器待执行的sql,然后再重写sql,添加物理分页语句和物理分页参数

134.mybatis 如何编写一个自定义插件?

1. 编写Interceptor的实现类

2. 使用@Intercepts注解完成插件签名 说明插件的拦截四大对象之一的哪一个对象的哪一个方法

3. 将写好的插件注册到全局配置文件中

十四、RabbitMQ

135.rabbitmq 的使用场景有哪些?

跨系统的异步通信

多个应用之间的耦合

应用内的同步变异步

消息驱动的架构

136.rabbitmq 有哪些重要的角色?

生产者,消费者,代理

137.rabbitmq 有哪些重要的组件?

ConnectionFactory(连接管理器)

Channel(信道)

Exchange(交换器)

Queue(队列)

RoutingKey(路由键)

BindingKey(绑定键)

138.rabbitmq vhost 的作用是什么?

虚拟的broker,最重要的是拥有独立的权限系统,可以做到vhost范围的用户控制

139.rabbitmq 的消息是怎么发送的?

必须连接到RabbitMQ服务器才能发布和消费消息,它们之间会创建一个tcp连接,一旦tcp打开并通过了认证,就会

创建一条amqp信道,信道是创建在真实tcp上的蓄奴链接,amqp命令都是通过信道发送出去

140.rabbitmq 怎么保证消息的稳定性?

提供事务的功能,通过将channel设置为confifirm模式

141.rabbitmq 怎么避免消息丢失?

消息持久化,ack确认机制,设置集群镜像模式,消息补偿机制

142.要保证消息持久化成功的条件有哪些?

声明队列必须设置持久化durable设置为rue

消息推送投递模式必须设置持久化,deliverymode设置为2

消息已经到达持久化交换器

消息已经到达持久化队列

以上都满足才能保证消息持久化成功

143.rabbitmq 持久化有什么缺点?

吃计划的缺点就是降低了服务器的吞吐量

因为使用的是磁盘而非内存存储

从而降低了吞吐量,可尽量使用ssd硬盘来缓解吞吐量问题

144.rabbitmq 有几种广播类型?

三种广播模式:fanoutdirecttopic

145.rabbitmq 怎么实现延迟消息队列?

通过消息过期后进入死信交换器再由交换器转发到延迟消费队列,实现延迟功能

使用RabbitMQ - deleayed - message-exchange 插件实现

146.rabbitmq 集群有什么用?

主要作用:

高可用:某个服务器出现问题,整个RabbitMQ还可以继续使用

高容量:集群可以承载更多的消息量

147.rabbitmq 节点的类型有哪些?

磁盘节点:消息会存储到磁盘

内存结点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型

148.rabbitmq 集群搭建需要注意哪些问题?

各节点之间使用“--link”连接,不能忽略

各节点使用的erlang cokkie值必须相同,此值相当于密钥的功能,用于各节点的认证

整个集群中必须包含一个磁盘节点

149.rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?

不是

存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样的新增节点不当没有新增存储空间,反而增加了更

多的冗余数据

性能的考虑:如果每条消息都需要完整拷贝到每一个节点,那新增节点并没有提升处理消息的能力,最多时保持和单

节点相同的性能甚至是更糟

150.rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?

不能创建队列

不能创建交换器

不能创建绑定

不能添加用户

不能更改权限

不能添加和删除集群节点

151.rabbitmq 对集群节点停止顺序有要求吗?

RabbitMQ 对集群的停止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。如果顺序恰好相反的话,

可能会造成消息的丢失。

十五、Kafka

152.kafka 可以脱离 zookeeper 单独使用吗?为什么?

kafka 不能脱离 zookeeper 单独使用,

因为 kafka 使用 zookeeper 管理和协调 kafka 的节点服务器。

153.kafka 有几种数据保留的策略?

kafka 有两种数据保存策略:

按照过期时间保留 按照存储的消息大小保留。

154.kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候

kafka 将如何处理?

这个时候 kafka 会执行数据清除工作,时间和大小不论那个满足条件,都会清空数据。

155.什么情况会导致 kafka 运行变慢?

cpu 性能瓶颈

磁盘读写瓶颈

网络瓶颈

156.使用 kafka 集群需要注意什么?

集群的数量不是越多越好,最好不要超过 7 个,

因为节点越多,消息复制需要的时间就越长,整个群组的吞吐量就越低。

集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。

十六、Zookeeper

157.zookeeper 是什么?

是一个分布式的,开发源码的分布式应用程序协调服务,一个分布式应用提供一致服务的软件,提供的功能:配置服

务,域名服务,分布式同步等

158.zookeeper 都有哪些功能?

集群管理,主节点选举,分布式锁,命名服务

159.zookeeper 有几种部署模式?

单机部署,集群部署,伪集群部署

160.zookeeper 怎么保证主从节点的状态同步?

zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 zab 协议。 zab

协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab 就进入了恢

复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保

证了 leader server 具有相同的系统状态

161.集群中为什么要有主节点?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,所以就需要主节点

162.集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?

可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用。

163.说一下 zookeeper 的通知机制?

客户端端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通

知,然后客户端可以根据 znode 变化来做出业务上的改变。

十七、MySql

164.数据库的三范式是什么?

一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。

第二范式(2NF):一个表描述一个事物,表里的所有列都与主键直接关联。

第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖 于非主键列 B,非主键列 B 依赖于主键的情况。

例如:员工表 员工id(主键) 员工姓名 部门id 部门名称(间接依赖员工id)  

165.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了 一条数据,此时 id 是几?

一般情况下,我们创建的表的类型是InnoDB,如果新增一条记录(不重启mysql的情况下),这条记录的id8;但是如果重启(文中提到的)MySQL的话,这条记录的ID6。因为InnoDB表只把自增主键的最大ID记录到内存中,

所以重启数据库或者对表OPTIMIZE操作,都会使最大ID丢失。 但是,如果我们使用表的类型是MylSAM,那么这条记录的ID就是8。因为MylSAM表会把自增主键的最大ID记录到数据文件里面,重启MYSQL后,自增主键的最大ID也不会丢失。

166.如何获取当前数据库版本?

一种方法:

打开mysql在命令提示符上输入 select version();如图

第二种方法:在cmd里面输入 mysql -V 来获取mysql版本号

167.说一下 ACID 是什么?

1.Atomicity 原子性

2.Consistency 一致性

3.Isolation 隔离性

4.Durability 耐久性

168.char varchar 的区别是什么?

char类型的长度是固定的,varchar的长度是可变的。

2.char类型的效率比varchar的效率稍高

3.varchar varchar2的区别

varchar2oracle开发的一个数据类型。

169.float double 的区别是什么?

float:4个字节

double: 8个字节

double float 的区别是double精度高,有效数字16,float精度7(可提供7位或8位有效数字,构成包括符号位、指数位和尾数位)

double消耗内存是float的两倍,double的运算速度比float慢得多,能用单精度时不要用双精度。

170.mysql 的内连接、左连接、右连接有什么区别?

1.内连接只显示两表中有关联的数据

2.左连接显示左表所有数据,右表没有对应的数据用NULL补齐,多了的数据不显示

171.mysql 索引是怎么实现的?

B+树索引

一、按表列属性分类:

1.单列索引

以表的单个列字段创建的索引

2.联合索引

以表的多个列字段组合创建的索引,在查询条件使用索引的从左字段顺序才会生效,遵循最左匹配原则。

单列索引和联合索引又包括:

普通索引

非主键,非唯一列的索引

主键索引

基于该表主键自动生成成的索引,如果未给表定义主键,会查找该表中是否存在非空、整形、唯一索引作为其

主键(可通过select _rowid from 表名查看),若都不满足会隐式生成一个rowid作为主键(无法直接查到)

唯一索引

基于表的唯一列生成的索引,允许为空值

全文索引

将存储于数据库中的整本书或整篇文章中任意内容信息查找出来,如大量级的文字中如like %关键字%,普通索引的效率与全文索引相比是非常低的。

172.怎么验证 mysql 的索引是否满足需求?

使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。 explain 语法:explain select * from table where type=1

173.说一下数据库的事务隔离?

Read uncommitted (读未提交):最低级别,以上问题均无法解决。

Read committed (读已提交):读已提交,可避免脏读情况发生。

Repeatable Read(可重复读):确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出现幻读问题。

Serializable (串行化):最严格的事务隔离级别,要求所有事务被串行执行,不能并发执行,可避免脏读、不可重复读、幻读情况的发生。

174.说一下 mysql 常用的引擎?

1. InnoDB

InnoDB 的存储文件有两个,后缀名分别是 .frm .idb,其中 .frm 是表的定义文件,而 idb 是数据文件。

InnoDB 中存在表锁和行锁,不过行锁是在命中索引的情况下才会起作用。InnoDB 支持事务,且支持四种隔离级别(读未提交、读已提交、可重复读、串行化),默认的为可重复读;而

Oracle 数据库中,只支持串行化级别和读已提交这两种级别,其中默认的为读已提交级别。

2. Myisam

Myisam 的存储文件有三个,后缀名分别是 .frm.MYDMYI,其中 .frm 是表的定义文件,.MYD 是数据文

件,.MYI 是索引文件。

Myisam 只支持表锁,且不支持事务。Myisam 由于有单独的索引文件,在读取数据方面的性能很高 。

3. 存储结构

InnoDB Myisam 都是用 B+Tree 来存储数据的。

175.说一下 mysql 的行锁和表锁?

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

176.说一下乐观锁和悲观锁?

悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别 人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其 它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之 前先上锁。JavasynchronizedReentrantLock等独占锁就是悲观锁思想的实现。

乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这

样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java

java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

两种锁的使用场景 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用

于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐

量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性

能,所以一般多写的场景下用悲观锁就比较合适。

乐观锁常见的两种实现方式 乐观锁一般会使用版本号机制或CAS算法实现。

177.mysql 问题排查都有哪些手段?   DBA

使用 show processlist 命令查看当前所有连接信息。

使用 explain 命令查询 SQL 语句执行计划。

开启慢查询日志,查看慢查询的 SQL

178.如何做 mysql 的性能优化?

为搜索字段创建索引。 比较稳定的字段可以设置索引,经常变化的字段不适合索引

避免使用 select *,列出需要查询的字段。

垂直分割分表。

选择正确的存储引擎。

十八、Redis

179.redis 是什么?都有哪些使用场景?

是一个高性能的(key/value)分布式内存数据库,基于内存运行 并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一, 也被人们称为数据结构服务器。

优点:

Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据,同时还提供listsetzsethash等数据结构的存储 Redis支持数据的备份,即 master-slave模式的数据备份

应用场景:

内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务 取最新N个数据的操作,如: 可以将最新的10条评论的ID放在RedisList集合里面 模拟类似于HttpSession这种需要设定过期时间的功能 发布、 订阅消息系统 定时器、计数器

180.redis 有哪些功能?

基于本机内存的缓存,服务端的Redis,持久化(Persistence)哨兵(Sentinel)和复制,(Replication)集群 (Cluster

181.redis memecache 有什么区别?

区别:

1、存储方式不同

memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小;redis有部份存在硬盘上,这样能保证数据的持久性,支持数据的持久化(笔者注:有快照和AOF日志两种持久化方式,在实际应用的时候,要特别注意配置文件快照参数,要不就很有可能服务器频繁满载做dump)。

2、数据支持类型不同

redis在数据支持上要比memecache多的多。

3、使用底层模型不同

新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4、运行环境不同

redis目前官方只支持LINUX 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上。

182.redis 为什么是单线程的?

redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案

183.什么是缓存穿透?怎么解决?

一.缓存穿透:

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决办法:

1.布隆过滤对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。还有最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避 免了对底层存储系统的查询压力。

2. 缓存空对象. null 变成一个值.也可以采用一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

.缓存雪崩

解决方法

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如RedisSETNX或者MemcacheADD)去set 一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过 期时间,让缓存失效的时间点尽量均匀

3.做二级缓存,或者双缓存策略。

4.缓存永远不过期

这里的永远不过期包含两层意思:

  1. 缓存上看,确实没设置过期时间
  2. 从功能上看,不过期就是静态数据数据

如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。大多数系统设计者考虑用加锁或者队列的方式

保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。

1. 加锁排队. 限流-- 限流算法. 1.计数 2.滑动窗口 3. 令牌桶Token Bucket 4.漏桶 leaky bucket [1]

2.数据预热

A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2A1缓存失效时间设置为短期,A2设置为长期。

(1) 从缓存上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是物理不过期。

(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,

通过一个后台的异步线程进行缓存的构建,也就是逻辑过期.1string(字符串)

memcached一样,一个key对应一个valuekey的最大存储值为512MBvalue的最大存储值也为512MB

184.redis 支持的数据类型有哪些?

string 类型是二进制安全的。意思是 redis string 可以包含任何数据。比如jpg图片或者序列化的对象。使用 设置和获取的命令为SETGET

命令为【SET key value】【GET key

2hash(哈希)

键值(key=>value)对集合。 是一个 string 类型的 field value 的映射表,hash 特别适合用于存储对象(每个 hash可以存储232次方 -1 键值对(40多亿))。使用设置和获取的命令为 HMSET, HGET

命令为【HMSET key key1 value1 key2 value2】【HGET key key1

3list(列表)

列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部(列表最多可存储2 32次方 - 1 元素 (4294967295, 每个列表可存储40多亿))。进值命令为LPUSH或者RPUSH,获取值命令为

LRANGE

命令为【LPUSH key value】【LRANGE key 0 10】获取key列表从左边开始010value

4set(集合)

Set string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中

最大的成员数为 232次方 - 1(4294967295, 每个集合可存储40多亿个成员)SADD添加一个 string 元素到

key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0

命令为【SADD key value】【SMEMBERS key

5zset(有序集合)

set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分

数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重

复。ZADD添加元素到集合,元素在集合中存在则更新对应score

185.redis 支持的 java 客户端都有哪些?

Redisson,Jedislettuce等等,官方推荐使用Redisson

186.jedis redisson 有哪些区别?

Jedis Redisson 都是Java中对Redis操作的封装。Jedis 只是简单的封装了 Redis API库,可以看作是Redis客户端,它的方法和Redis 的命令很类似。Redisson 不仅封装了 redis ,还封装了对更多数据结构的支持,以及锁等功能,相比于Jedis 更加大。但Jedis相比于Redisson 更原生一些,更灵活

187.怎么保证缓存和数据库数据的一致性?

将不一致分为三种情况:

1. 数据库有数据,缓存没有数据;

2. 数据库有数据,缓存也有数据,数据不相等;

3. 数据库没有数据,缓存有数据。

保证缓存和数据库数据的一致性:

1. 首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。

2. 需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。

188.redis 持久化有几种方式?

RDBRDB 持久化机制,是对 redis 中的数据执行周期性的持久化。AOFAOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,在 redis 重启的时

候,可以通过回放 AOF 日志中的写入指令来重新构建整个数据集。

189.redis 怎么实现分布式锁?

分布式锁常见的三种实现方式:

1. 数据库乐观锁;

2. 基于Redis的分布式锁;

3. 基于ZooKeeper的分布式锁。

Redis的分布式锁;

1.加锁

最简单的方法是使用setnx命令。key是锁的唯一标识,按业务来决定命名。比如想要给一种商品的秒杀活动加锁,可以给key命名为 “lock_sale_商品ID” 。而value设置成什么呢?锁的value值为一个随机生成的UUID。我们

可以姑且设置成1。加锁的伪代码如下:

setnxkey1) 当一个线程执行setnx返回1,说明key原本不存在,该线程成功得到了锁;当一个线程执行setnx返回0,说明key已经存在,该线程抢锁失败。

2.解锁

有加锁就得有解锁。当得到锁的线程执行完任务,需要释放锁,以便其他线程可以进入。释放锁的最简单方式

是执行del指令,伪代码如下:

delkey) 释放锁之后,其他线程就可以继续执行setnx命令来获得锁。

3.锁超时

锁超时是什么意思呢?如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资源将会永远被锁住,别的线程再也别想进来。

所以,setnxkey必须设置一个超时时间,单位为second,以保证即使没有被显式释放,这把锁也要在一定时间后自动释放,避免死锁。setnx不支持超时参数,所以需要额外的指令,伪代码如下:

expirekey 30

190.redis 分布式锁有什么缺陷?

1. Redis 分布式锁不能解决超时的问题

2. 分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

191.redis 如何做内存优化?

1、缩减键值对象

  缩减键(key)和值(value)的长度,

key长度:如在设计键时,在完整描述业务情况下,键值越短越好。

value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组放入Redis。首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据。其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小。以JAVA为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如: protostuff,kryo等,下图是JAVA常见序列化工具空间压缩对比。

2、共享对象池

  对象共享池指Redis内部维护[0-9999]的整数对象池。创建大量的整数类型redisObject存在内存开销,每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。所以Redis内存维护一个[0-9999]的整数对象池,用于节约内存。 除了整数值对象,其他类型如list,hash,set,zset内部元素也可以使用整数对象池。因此开发中在满足需求的前提下,尽量使用整数对象以节省内存。

3、控制key的数量

十九、JVM

192.说一下类加载的执行过程?

java程序在执行过程中,类,对象以及它们成员加载、初始化的顺序如下:

1、首先加载要创建对象的类及其直接与间接父类。

2、在类被加载的同时会将静态成员进行加载,主要包括静态成员变量的初始化,静态语制句块的执

行,在加载时按代码的先后顺序进行。

 3、需要的类加载完成后,开始创建对象,首先会加载非静态的成员,主要包 括非静态成员变量的初始化,非静态语句块的执行,在加载时按代码的先后顺序进行。

4、最后执zd行构造器,构造器执行完毕,对象生成。

193.常用的 jvm 调优的参数都有哪些?

本文章参数根据后期用的参数会持续更新 ---

1-Xms20M

表示设置JVM启动内存的最小值为20M,必须以M为单位

2-Xmx20M

表示设置JVM启动内存的最大值为20M,必须以M为单位。将-Xmx-Xms设置为一样可以避免JVM内存自动扩展。大

的项目-Xmx-Xms一般都要设置到10G20G甚至还要高

3-verbose:gc

表示输出虚拟机中GC的详细情况

4-Xss128k

表示可以设置虚拟机栈的大小为128k

5-Xoss128k

表示设置本地方法栈的大小为128k。不过HotSpot并不区分虚拟机栈和本地方法栈,因此对于HotSpot来说这个参数

是无效的

6-XX:PermSize=10M

表示JVM初始分配的永久代(方法区)的容量,必须以M为单位

7-XX:MaxPermSize=10M

表示JVM允许分配的永久代(方法区)的最大容量,必须以M为单位,大部分情况下这个参数默认为64M

8-Xnoclassgc

表示关闭JVM对类的垃圾回收

9-XX:+TraceClassLoading

表示查看类的加载信息

10-XX:+TraceClassUnLoading

表示查看类的卸载信息

11-XX:NewRatio=4

表示设置 年轻代(包括Eden和两个Survivor区)/老年代 的大小比值为14,这意味着年轻代占整个堆的1/5

12-XX:SurvivorRatio=8表示设置2Survivor区:1Eden区的大小比值为2:8,这意味着Survivor区占整个年轻代的1/5,这个参数默认为8

13-Xmn20M

表示设置年轻代的大小为20M

14-XX:+HeapDumpOnOutOfMemoryError

表示可以让虚拟机在出现内存溢出异常时Dump出当前的堆内存转储快照

15-XX:+UseG1GC

表示让JVM使用G1垃圾收集器

16-XX:+PrintGCDetails

表示在控制台上打印出GC具体细节

17-XX:+PrintGC

表示在控制台上打印出GC信息

18-XX:PretenureSizeThreshold=3145728

表示对象大于31457283M)时直接进入老年代分配,这里只能以字节作为单位

19-XX:MaxTenuringThreshold=1

表示对象年龄大于1,自动进入老年代,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于

年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,

这样可以增加对象在年轻代的存活时间,增加在年轻代被回收的概率。

20-XX:CompileThreshold=1000

表示一个方法被调用1000次之后,会被认为是热点代码,并触发即时编译

21-XX:+PrintHeapAtGC

表示可以看到每次GC前后堆内存布局

22-XX:+PrintTLAB

表示可以看到TLAB的使用情况

23-XX:+UseSpining

开启自旋锁

24-XX:PreBlockSpin

更改自旋锁的自旋次数,使用这个参数必须先开启自旋锁

25-XX:+UseSerialGC

表示使用jvm的串行垃圾回收机制,该机制适用于丹cpu的环境下

26-XX:+UseParallelGC

表示使用jvm的并行垃圾回收机制,该机制适合用于多cpu机制,同时对响应时间无强硬要求的环境下,使用-

XX:ParallelGCThreads=设置并行垃圾回收的线程数,此值可以设置与机器处理器数量相等。

27-XX:+UseParallelOldGC表示年老代使用并行的垃圾回收机制

28-XX:+UseConcMarkSweepGC

表示使用并发模式的垃圾回收机制,该模式适用于对响应时间要求高,具有多cpu的环境下

29-XX:MaxGCPauseMillis=100

设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。

30-XX:+UseAdaptiveSizePolicy

设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低响应时间

或者收集频率等,此值建议使用并行收集器时,一直打开

算法题

1)请简单解释算法是什么?

算法是一个定义良好的计算过程,它将一些值作为输入并产生相应的输出值。简单来说,它是将输入转换为输出的一系列计算步骤。

2)解释什么是快速排序算法?

快速排序算法能够快速排序列表或查询。它基于分割交换排序的原则,这种类型的算法占用空间较小,它将待排序列

表分为三个主要部分:

小于Pivot的元素

枢轴元素Pivot(选定的比较值)

大于Pivot的元素

写一个快速排序的

Linux常用命令

https://blog.csdn.net/qq_23329167/article/details/83856430

一、基本命令

1.1 关机和重启

关机 shutdown -h now 立刻关机 shutdown -h 5 5分钟后关机 poweroffff 立刻关机 重启 shutdown -r now 立刻重启

shutdown -r 5 5分钟后重启 reboot 立刻重启

1.2 帮助命令

--help命令 shutdown --helpifconfifig --help:查看网卡信息

man命令(命令说明书) man shutdown 注意:man shutdown打开命令说明书之后,使用按键q退出

二、目录操作命令

2.1 目录切换 cd

命令:cd 目录

cd / 切换到根目录 cd /usr 切换到根目录下的usr目录 cd ../ 切换到上一级目录 或者 cd .. cd ~ 切换到home目录 cd -

切换到上次访问的目录

2.2 目录查看 ls [-al]

命令:ls [-al]

ls 查看当前目录下的所有目录和文件 ls -a 查看当前目录下的所有目录和文件(包括隐藏的文件) ls -l ll 列表查看

当前目录下的所有目录和文件(列表查看,显示更多信息) ls /dir 查看指定目录下的所有目录和文件 如:ls /usr

2.3 目录操作【增,删,改,查】 2.3.1 创建目录【增】 mkdir 命令:mkdir 目录

mkdir aaa 在当前目录下创建一个名为aaa的目录 mkdir /usr/aaa 在指定目录下创建一个名为aaa的目录

2.3.2 删除目录或文件【删】rm

命令:rm [-rf] 目录

删除文件: rm 文件 删除当前目录下的文件 rm -f 文件 删除当前目录的的文件(不询问)删除目录: rm -r aaa 递归删除当前目录下的aaa目录 rm -rf aaa 递归删除当前目录下的aaa目录(不询问)

全部删除: rm -rf * 将当前目录下的所有目录和文件全部删除 rm -rf /* 【自杀命令!慎用!慎用!慎用!】将根目

录下的所有文件全部删除

注意:rm不仅可以删除目录,也可以删除其他文件或压缩包,为了方便大家的记忆,无论删除任何目录或文件,都

直接使用 rm -rf 目录/文件/压缩包

2.3.3 目录修改【改】mv cp

一、重命名目录

命令:mv 当前目录 新目录

例如:mv aaa bbb 将目录aaa改为bbb

注意:mv的语法不仅可以对目录进行重命名而

且也可以对各种文件,压缩包等进行 重命名的操作

二、剪切目录

命令:mv 目录名称 目录的新位置

示例:将/usr/tmp目录下的aaa目录剪切到 /usr目录下面 mv /usr/tmp/aaa /usr

注意:mv语法不仅可以对目录进行剪切操作,对文件和压缩包等都可执行剪切操作

三、拷贝目录

命令:cp -r 目录名称 目录拷贝的目标位置 -r代表递归

示例:将/usr/tmp目录下的aaa目录复制到 /usr目录下面 cp

/usr/tmp/aaa /usr

注意:cp命令不仅可以拷贝目录还可以拷贝文件,压缩包等,拷贝文件和压缩包时不 用写-r递归

2.3.4 搜索目录【查】fifind

命令:fifind 目录 参数 文件名称 示例:fifind /usr/tmp -name 'a*' 查找/usr/tmp目录下的所有以a开头的目录或文件

三、文件操作命令

3.1 文件操作【增,删,改,查】

3.1.1 新建文件【增】touch

命令:touch 文件名 示例:在当前目录创建一个名为aa.txt的文件 touch aa.txt

3.1.2 删除文件 【删】 rm

命令:rm -rf 文件名

3.1.3 修改文件【改】 vivim

vi编辑器的3种模式】 基本上vi可以分为三种状态,分别是命令模式(command mode)、插入模式(Insert

mode)和底行模式(last line mode),各模式的功能区分如下: 1) 命令行模式command mode) 控制屏幕光标

的移动,字符、字或行的删除,查找,移动复制某区段及进入Insert mode下,或者到 last line mode。 命令行模式

下的常用命令: 【1】控制光标移动:j 2】删除当前行:dd 3】查找:/字符 【4】进入编辑模式:i o a

5】进入底行模式::

2) 编辑模式(Insert mode) 只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。 编辑模

式下常用命令: 【1ESC 退出编辑模式到命令行模式;

3) 底行模式(last line mode) 将文件保存或退出vi,也可以设置编辑环境,如寻找字符串、列出行号……等。 底行

模式下常用命令: 【1】退出编辑: :q 2】强制退出: :q! 3】保存并退出: :wq

打开文件命令:vi 文件名 示例:打开当前目录下的aa.txt文件 vi aa.txt 或者 vim aa.txt

注意:使用vi编辑器打开文件后,并不能编辑,因为此时处于命令模式,点击键盘i/a/o进入编辑模式。

编辑文件

使用vi编辑器打开文件后点击按键:i a或者o即可进入编辑模式。

i:在光标所在字符前开始插入 a:在光标所在字符后开始插入 o:在光标所在行的下面另起一新行插入

保存或者取消编辑

保存文件:

第一步:ESC 进入命令行模式 第二步:: 进入底行模式 第三步:wq 保存并退出编辑

取消编辑:

第一步:ESC 进入命令行模式 第二步:: 进入底行模式 第三步:q! 撤销本次修改并退出编辑

3.1.4 文件的查看【查】

文件的查看命令:cat/more/less/tail

cat:看最后一屏

示例:使用cat查看/etc/sudo.conf文件,只能显示最后一屏内容 cat sudo.conf

more:百分比显示

示例:使用more查看/etc/sudo.conf文件,可以显示百分比,回车可以向下一行,空格可以向下一页,q可以退出查

more sudo.conf

less:翻页查看

示例:使用less查看/etc/sudo.conf文件,可以使用键盘上的PgUpPgDn向上 和向下翻页,q结束查看 less

sudo.conf

tail:指定行数或者动态查看

示例:使用tail -10 查看/etc/sudo.conf文件的后10行,Ctrl+C结束

tail -10 sudo.conf

3.2 权限修改 rwxr代表可读,w代表可写,x代表该文件是一个可执行文件,如果rwx任意位置变为-则代表不可读

或不可写或不可执行文件。

示例:给aaa.txt文件权限改为可执行文件权限,aaa.txt文件的权限是-rw-------

第一位:-就代表是文件,d代表是文件夹 第一段(3位):代表拥有者的权限 第二段(3位):代表拥有者所在的

组,组员的权限 第三段(最后3位):代表的是其他用户的权限

421 421 421

rw- --- ---

命令:chmod +x aaa.txt 或者采用8421法 命令:chmod 100 aaa.txt

四、压缩文件操作

4.1 打包和压缩

Windows的压缩文件的扩展名 .zip/.rar linux中的打包文件:aa.tar

linux中的压缩文件:bb.gz

linux中打包并压缩的文件:.tar.gz

Linux中的打包文件一般是以.tar结尾的,压缩的命令一般是以.gz结尾的。 而一般情况下打包和压缩是一起进行的,

打包并压缩后的文件的后缀名一般.tar.gz

命令:tar -zcvf 打包压缩后的文件名 要打包的文件 其中:z:调用gzip压缩命令进行压缩 c:打包文件 v:显示运行

过程 f:指定文件名

示例:打包并压缩/usr/tmp 下的所有文件 压缩后的压缩包指定名称为xxx.tar tar -zcvf ab.tar aa.txt bb.txt 或:tar -

zcvf ab.tar *

4.2 解压

命令:tar [-zxvf] 压缩文件

其中:x:代表解压 示例:将/usr/tmp 下的ab.tar解压到当前目录下

示例:将/usr/tmp 下的ab.tar解压到根目录/usr tar -xvf ab.tar -C /usr------C代表指定解压的位置

五、查找命令

5.1 grep

grep命令是一种强大的文本搜索工具

使用实例:

ps -ef | grep sshd 查找指定ssh服务进程 ps -ef | grep sshd | grep -v grep 查找指定服务进程,排除gerpps -ef |

grep sshd -c 查找指定进程个数 5.2 fifind fifind命令在目录结构中搜索文件,并对搜索结果执行指定的操作。

fifind 默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。

使用实例:

fifind . -name ".log" -ls 在当前目录查找以.log结尾的文件,并显示详细信息。 fifind /root/ -perm 600 查找/root/目录下

权限为600的文件 fifind . -type f -name ".log" 查找当目录,以.log结尾的普通文件 fifind . -type d | sort 查找当前所有目

录并排序 fifind . -size +100M 查找当前目录大于100M的文件

十、其他命令

10.1 查看当前目录:pwd

命令:pwd 查看当前目录路径

10.2 查看进程:ps -ef

命令:ps -ef 查看所有正在运行的进程

10.3 结束进程:kill

命令:kill pid 或者 kill -9 pid(强制杀死进程) pid:进程号10.4 网络通信命令:

ifconfifig:查看网卡信息

命令:ifconfifig ifconfifig | more

ping:查看与某台机器的连接情况

命令:ping ip

netstat -an:查看当前系统端口

命令:netstat -an

搜索指定端口 命令:netstat -an | grep 8080

10.5 配置网络

命令:setup

10.6 重启网络

命令:service network restart

10.7 切换用户

命令:su - 用户名

10.8 关闭防火墙

命令:chkconfifig iptables offff

或者:

iptables -L; iptables -F; service iptables stop 10.9 修改文件权限 命令:chmod 777

10.10 清屏

命令:ctrl + l