JAVA初/中/高级程序员必须知道的知识

面试题模块介绍
我们这份面试题,包含的内容了十九了模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示:
在这里插入图片描述

可能对于初学者不需要后面的框架和 JVM 模块的知识,读者朋友们可根据自己的情况,选择对应的模块进行阅读。

适宜阅读人群
需要面试的初/中/高级 java 程序员
想要查漏补缺的人
想要不断完善和扩充自己 java 技术栈的人
java 面试官
具体面试题
下面一起来看 208 道面试题,具体的内容。

一、Java 基础

1.JDK 和 JRE 有什么区别?

 1. JDK,开发java程序用的开发包,JDK里面有java的运行环境(JRE),包括client和server端的。需要配置环境变量。
 2. JRE,运行java程序的环境,JVM,JRE里面只有client运行环境,安装过程中,会自动添加PATH。

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

 1. ==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。(比较地址值即是指是否为同一个对象的引用)
    对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
    如果作用于引用类型的变量,则比较的是所指向的对象的地址
    
 2. equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比一般是比较对象的属性。 
     对于equals方法,注意:equals方法不能作用于基本数据类型的变量
     如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
     诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

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

`1. 不一定相同。正常情况下,因为equals()方法比较的就是对象在内存中的值,如果值相同,那么Hashcode值也应该相同。但是如果不重写hashcode方法,就会出现不相等的情况。`

4.final 在 java 中有什么作用?

 1. final关键字可以用于三个地方。用于修饰类、类属性和类方法。
    被final关键字修饰的类不能被继承,被final关键字修饰的类属性和类方法不能被覆盖(重写);
    对于被final关键字修饰的类属性而言,子类就不能给他重新赋值了,如果重新赋值,会报错:
    重写:只要子类方法与父类方法同名同参数就是重写。

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

1. `首先与 -1.5最接近的有两个整数 -1和 -2,取较大的那结果就是-1;`

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

 1. 不是,String是类代表字符串,属于引用类型,所谓引用类型包括:类,接口,数组...
    java中的基本类型一共有8个,它们分别为:
	1) 四种整数类型(byte、short、int、long)
	2 )两种浮点数类型(float、double)
	3 )一种字符类型(char)
	4 )一种布尔类型(boolean):true 真  和 false 假。
	5)类型转换:char--> 自动转换:byte-->short-->int-->long-->float-->double

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

 1.字符串池
	池中String的hashCode是唯一的。
	 attentions:
    (1)使用new操作创建的字符串对象不在池中。
    (2)计算得来的字符串不在池中。
    (3)只有编译期确定的对象直接被放入池中或指向池中对象。
    (4)使用==操作符号比较字符串时,必须值和hashCode值同时相等时,两个字符串才相等。
    (5)intern只会在字符串池中寻找匹配的对象,没有找到的话,自动将自己放入池内。

2.equals和hashCode
	在重写equals时遵循以下约定:自反性、对称性、传递型、一致性
    在重写hashCode时遵循以下约定:(1)相等对象,hashCode一定相等;(2)不等对象,hashCode            不一定不相等;(3)hashCode相等,不一定对象相等;(4)hashCode不相等,对象一定不相等。
	
	StringBuffer 和 StringBuilder中常用的函数:
    append:向缓冲区末尾添加字符串。
    delete:删除指定位置的字符串。
    replace:替换指定字符串。
    inset:在指定位置插入字符串。
    indexOf:指定的字符串所在的位置索引。
    lastIndexOf:最后一个匹配指定的字符串的位置索引。
    reverse:反转整个字符串。 
    对于频繁变化的字符串,不要使用String,而要使用StringBuffer或者StringBuilder,在单线程程序中使用		    StringBuilder,多线程环境中建议使用StringBuffer。

3.格式化输出
    %[-][有效位数][.精度]转换字符

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

不一样,第一个只分配一次内存空间;第二个分配了两次内存空间,当然,第一次分配的空间因为不可到达而被GC回收。

9.如何将字符串反转?

思路1: 运用递归的方法进行反转

假设反转方法为 reverseString(String str)
1)当字符串为空或者只有一个字符时,返回原字符
2)当字符串有两个以上(长度为len)的字符时,反转后的字符串为 第二个字符开始的子串的反转结果+第		一个字符, 即 reverseString(str.subString(1))+str.charAt(0);

   代码实现如下:
   public String reverseStringRecur(String str) {
       if ((str == null) || str.length() <2) return str;
       return  reverseString(str.subString(1))+str.charAt(0);
    }	

10.String 类的常用方法都有那些?
在这里插入图片描述

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

     抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。
如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

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

1.首先应该知道,抽象类是不能被实例化的,就是不能用new调出构造方法创建对象,而普通类则反之!
2.抽象类的访问权限限于Public和Protected,因为抽象类的方法是需要继承之后让子类去实现的,如果为Private,则无法被子类继承,子类也无法实现该方法
3.如果一个类继承于抽象类,则该子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类。

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

1.java类一旦被声明为abstract(抽象类),必须要继承或者匿名(其实匿名也是种继承)才能使用。
而final则是让该类无法被继承,所以final是必然不能和abstract同时声明的
2.但是private呢?
一个类被声明为private的时候,它当然是内部类,内部类是可以被它的外部类访问到的,所以,可以继承,private和abstract不冲突。

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

1.抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。以JDK中的GenericServlet为例
2.接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。以Externalizable接口为例

在这里插入图片描述

15.java 中 IO 流分为几种?

1.按流向分(站在程序角度考虑)
	输入流(input)
	输出流(output)

2.按类型分:
	字节流(InputStream/OutputStream)
	任何文件都可以通过字节流进行传输。
	
	字符流(Reader/Writer)
	非纯文本文件,不能用字符流,会导致文件格式破坏,不能正常执行。

3.节点流(低级流:直接跟输入输出源对接)
	FileInputStream/FileOutputStream/FileReader/FileWriter/PrintStream/PrintWriter.

4.处理流(高级流:建立在低级流的基础上)
	转换流:InputStreamReader/OutputStreamWriter,字节流转字符流/字符流转字节流
	
	缓冲流:BufferedInputStream/BufferedOutputStream   BufferedReader/BufferedReader可对节点流经行包装,使读写更快

他们各自的优缺点:
  字符流按字符处理数据,速度较之于同原理的字节流快,但是使用范围较小,仅限文本文件;
  字节流处理范围广,文本,音频,视频都可以处理。

16.BIO、NIO、AIO 有什么区别?

	1.同步阻塞I/O(BIO):
	   同步阻塞I/O,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制来改善。BIO方式适用于连接数目比较小且固定的架构,这种方式对服务端资源要求比较高,并发局限于应用中,在jdk1.4以前是唯一的io现在,但程序直观简单易理解
	2.同步非阻塞I/O(NIO):
	同步非阻塞I/O,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,jdk1,4开始支持
	3.异步非阻塞I/O(AIO):
	异步非阻塞I/O,服务器实现模式为一个有效请求一个线程,客户端的IO请求都是由操作系统先完成了再通知服务器用其启动线程进行处理。AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,jdk1.7开始支持。
	4.IO与NIO区别:
	1)IO面向流,NIO面向缓冲区
	2)IO的各种流是阻塞的,NIO是非阻塞模式
	3)Java NIO的选择允许一个单独的线程来监视多个输入通道,可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入或选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道 
	5.同步与异步的区别:
	同步:发送一个请求,等待返回,再发送下一个请求,同步可以避免出现死锁,脏读的发生
    异步:发送一个请求,不等待返回,随时可以再发送下一个请求,可以提高效率,保证并发

   同步异步关注点在于消息通信机制,
   阻塞与非阻塞关注的是程序在等待调用结果时(消息、返回值)的状态:
       阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
	   非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程

   不同层次:
   CPU层次:操作系统进行IO或任务调度层次,现代操作系统通常使用异步非阻塞方式进行IO(有少部分IO可能会使用同步非阻塞),即发出IO请求后,并不等待IO操作完成,而是继续执行接下来的指令(非阻塞),IO操作和CPU指令互不干扰(异步),最后通过中断的方式通知IO操作的完成结果。

    线程层次:操作系统调度单元的层次,操作系统为了减轻程序员的思考负担,将底层的异步非阻塞的IO方式进行封装,把相关系统调用(如read和write)以同步的方式展现出来,然而同步阻塞IO会使线程挂起,同步非阻塞IO会消耗CPU资源在轮询上,3个解决方法;
    
    多线程(同步阻塞)
    IO多路复用(select、poll、epoll)
    直接暴露出异步的IO接口,kernel-aio和IOCP(异步非阻塞) 
    
    Linux IO模型:
    阻塞/非阻塞:等待I/O完成的方式,阻塞要求用户程序停止执行,直到IO完成,而非阻塞在IO完成之前还可以继续执行
    同步/异步:获知IO完成的方式,同步需要时刻关心IO是否完成,异步无需主动关心,在IO完成时它会收到通知

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

创建:
createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false。
mkdir()  在指定位置创建一个单级文件夹。
mkdirs()  在指定位置创建一个多级文件夹。
renameTo(File dest)如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名, 如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。 

删除:
delete()  删除文件或者一个空文件夹,不能删除非空文件夹,马上删除文件,返回一个布尔值。
deleteOnExit()jvm退出时删除文件或者文件夹,用于删除临时文件,无返回值。
 判断:
exists()  文件或文件夹是否存在。
isFile()  是否是一个文件,如果不存在,则始终为false。
isDirectory()  是否是一个目录,如果不存在,则始终为false。
isHidden()  是否是一个隐藏的文件或是否是隐藏的目录。
isAbsolute()  测试此抽象路径名是否为绝对路径名。
 获取:
getName()  获取文件或文件夹的名称,不包含上级路径。
getAbsolutePath()获取文件的绝对路径,与文件是否存在没关系
length()  获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
getParent()  返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
lastModified()获取最后一次被修改的时间。

 文件夹相关:
static File[] listRoots()列出所有的根目录(Window中就是所有系统的盘符)
list()  返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
listFiles()  返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
list(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
listFiles(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。

二、容器

18.java 容器都有哪些?

    Java中提供的其实只有4中容器:Map、List、Set和Queue。
    Java提供了大量的持有对象方式:
    1、数组将数字与对象联系起来。它保存类型明确的对象,查询对象是,不需要对结果做类型转换。他可以是多维的,可以保存基本类型的数据。但是,数组一旦生成,其容量就不能改变。
    2、Collection保存单一的元素,而Map保存相关联的键值对。有了Java的泛型,就可以指定容器中存放的对象类型,因此就不会将错误类型的对象防止到容器中,而且在容器中获取元素时,不必进行类型转换。各种Collection和Map都可以在向其中添加更多的元素时,自动调整其尺寸。容器不能持有基本类型,但是自动包装机制会仔细地执行基本类型到容器中所持有的包装器类型之间的双向转换。
    3、像数组一样,List也建立数字索引与对象的关联,因此,数组和List都是排序好的容器。List能够自动扩充容量。
    4、如果要进行大量的随机访问,就是用ArrayList。如果要经常从表中间插入或删除元素,则应该使用LinkedList。
    5、各种Queue以及栈的行为,有LinkedList提供支持。
    6、Map是一种将对象与对象相关联的设计。HashMap设计用来快速访问TreeMap保存“键”始终处于排序状态(没有HashMap快);LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问能力。
    7、Set不接受重复元素。HashSet提供最快的查询速度,TreeSet保持元素处于排序状态。LinkedHashSet以出入顺序保存元素。
    详细信息:https://www.cnblogs.com/yanspecial/p/5611542.html

19.Collection 和 Collections 有什么区别?

1、Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。

2、Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。

20.List、Set、Map 之间的区别是什么?

List:
		1.可以允许重复的对象。
   2.可以插入多个null元素。
        3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
        4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。
        
Set:
		1.不允许重复对象
   2. 无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator  或者 Comparable 维护了一个排序顺序。
        3. 只允许一个 null 元素
        4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。
        
Map:      
		1.Map不是collection的子接口或者实现类。Map是一个接口。
		2.Map 的每个Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
		3. TreeMap 也通过 Comparator  或者 Comparable 维护了一个排序顺序。
		4. Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
		5.Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用) 

21.HashMap 和 Hashtable 有什么区别?

1.它们所继承的类不一样。
HashTable和HashMap都实现了Map接口,但是它们所继承的类时不同的。HashTable继承了Dictionary类(Dictionary类已经过时),而HashMap则是继承了AbstractMap类。

2..HashTable是线程安全的,HashMap是线程不安全的。
HashTable是同步的,也就是说,它是线程安全的,它是实现了Serializable;

HashMap也同样实现了Serializable,但是根据文档所述,HashMap这个类其实是不同步的,也就是说,HashMap是线程不安全的。(可以使用Collections.synchronizedMap(new HashMap())获取一个线程安全的Map);

3.HashTable不允许null作为key和value,而HashMap允许null作为key和value。
在HashMap中,只能有一条记录使用null作为key,但是可以有任意条value为null的记录。

最后,HashMap比HashTable拥有更多的方法,也更新。所以尽可能使用HashMap进行开发。

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

HashMap:适用于在Map中插入、删除和定位元素。 
TreeMap:适用于按自然顺序或自定义顺序遍历键(key)。 

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

HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry

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

对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,更确切的说,HashSet中的元素,只是存放在了底层HashMap的key上, 而value使用一个static final的Object对象标识。因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成
总结:
HashSet底层由HashMap实现
HashSet的值存放于HashMap的key上
HashMap的value统一为PRESENT

25.ArrayList 和 LinkedList 的区别是什么?

      1. ArrayList的实现是基于数组,LinkedList的实现是基于双向链表。
       
      2. 对于随机访问,ArrayList优于LinkedList,ArrayList可以根据下标以O(1)时间复杂度对元素进行随机访问。而LinkedList的每一个元素都依靠地址指针和它后一个元素连接在一起,在这种情况下,查找某个元素的时间复杂度是O(n) 
      
      3. 对于插入和删除操作,LinkedList优于ArrayList,因为当元素被添加到LinkedList任意位置的时候,不需要像ArrayList那样重新计算大小或者是更新索引。 
      
  4. LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

26.如何实现数组和 List 之间的转换?

ArrayList<Element> arrayList = new ArrayList<Element>(Arrays.asList(array));

首先,我们来看下ArrayList的构造方法的文档。 
ArrayList(Collection < ? extends E > c) : 构造一个包含特定容器的元素的列表,并且根据容器迭代器的顺序返回。 
所以构造方法所做的事情如下: 
1.将容器c转换为一个数组 
2.将数组拷贝到ArrayList中称为”elementData”的数组中 

27.ArrayList 和 Vector 的区别是什么?

1.ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。
2.Vector提供indexOf(obj, start)接口,ArrayList没有。
3.Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。 

28.Array 和 ArrayList 有何区别?

Array数组可以包含基本类型和对象类型,
ArrayList却只能包含对象类型。

Array数组在存放的时候一定是同种类型的元素。
ArrayList就不一定了,因为ArrayList可以存储Object。

Array([]):最高效;但是其容量固定且无法动态改变;
ArrayList:  容量可动态增长;但牺牲效率;

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

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回null,但是 remove() 失败的时候会抛出NoSuchElementException异常。

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

vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。

statck:堆栈类,先进后出

hashtable:就比hashmap多了个线程安全

enumeration:枚举,相当于迭代器

线程安全的类其方法是同步的,每次只能一个访问。是重量级对象,效率较低。

31.迭代器 Iterator 是什么?

    迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

    集合体系中的迭代器就是遍历,集合取出元素的方式,迭代器可以取出并操作集合中的元素

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

    Java中的Iterator功能比较简单,并且只能单向移动:
  (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
  (2) 使用next()获得序列中的下一个元素。
  (3) 使用hasNext()检查序列中是否还有元素。
  (4) 使用remove()将迭代器新返回的元素删除。
    
    迭代器的特点:
    1每个集合都有存和取的方式,而且每个集合的数据结构不一样,所以他们存和取的动作也不一样,添加通过add()能完成添加操作,但是取的动作比较复杂,所以把取的动作封装成了对象,包含hasNext() next() remove()三个共同的方法,由于集合本身最知道该怎么取元素和迭代器对象需要用到集合内部的元素,所以把迭代器封装成了集合类的内部类,通过一个方法把迭代器提供给外部,iterator()

33.Iterator 和 ListIterator 有什么区别?

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

2. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

3. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。

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

迭代器再帮助我们进行对集合的元素进行遍历提供了有效的方法,java采用迭代器模式能在不暴露集合对象内部元素的情况下,对元素进行访问。

三、多线程

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

解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
解释三:在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群

所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

36.线程和进程的区别?

    (1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
    (2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
    (3)线程是处理器调度的基本单位,但进程不是.
    (4)二者均可并发执行.
    
一个程序至少有一个进程,一个进程至少有一个线程. 

线程的划分尺度小于进程,使得多线程程序的并发性高。
 
每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 

多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

37.守护线程是什么?

只要当前JVM实例中尚存任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作,Daemon作用是为其他线程提供便利服务,守护线程最典型的应用就是GC(垃圾回收器)

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

1、通过继承Thread类创建线程
(1).首先定义一个类去继承Thread父类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).直接创建一个ThreadTest类的对象,也可以利用多态性,变量声明为父类的类型。
(3).调用start方法,线程启动,隐含的调用run()方法。 

2、通过实现Runnable接口创建线程
(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).创建Runnable接口实现类的对象。
(3).创建一个ThreadTest类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)
(4).调用Thread对象的start()方法,启动线程

3.通过Callable和Future创建线程
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

40.线程有哪些状态?

线程状态有 5 种,新建,就绪,运行,阻塞,死亡。关系图如下:
在这里插入图片描述

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

 1.这两个方法来自不同的类分别是Thread和Object
 2.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得敏感词线程可以使用同步控制块或者方法。
 3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
    任何地方使用
 4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

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

notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。

void notify(): 唤醒一个正在等待该对象的线程。
void notifyAll(): 唤醒所有正在等待该对象的线程。

两者的最大区别在于:
notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。

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

Run() : 
run()就是个普通方法,可以调用执行,但是是同步调用,没有异步的效果。
Run()方法就是个普通方法,可以调用多次

Start(): 
通知线程规划期,此线程已经准备就绪,等待调用线程对象的run()的方法。就是让系统安排一个时间来调用Thread的run()方法,使得按异步的方法执行run方法。
不能多次调用一个实例的Start()方法,会抛出异常。(特别说明:一个线程执行完后,不太可能重新运行)

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

 Java通过Executors提供四种线程池,分别为:
 1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
 2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
 3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
 4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。	
 链接:[https://blog.csdn.net/baidu_32492845/article/details/78621415]

45.线程池都有哪些状态?
在这里插入图片描述

1、RUNNING
线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务(堵塞队列中的任务)进行处理。 
线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0
2、 SHUTDOWN
线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
3、STOP
线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。 
调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4、TIDYING
当所有的任务已终止,ctl(有效线程数)记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5、 TERMINATED
线程池彻底终止,就变成TERMINATED状态。
线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

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

一:
submit()方法,可以提供Future < T > 类型的返回值。
executor()方法,无返回值。
二:
excute方法会抛出异常。
sumbit方法不会抛出异常。除非你调用Future.get()。
三:
excute入参Runnable
submit入参可以为Callable

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

	一、线程安全在三个方面体现
	
    1.原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
    
    2.可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
    
    3.有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。

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

自旋锁(CAS):让不满足条件的线程等待一会看能不能获得锁,通过占用处理器的时间来避免线程切换带来的开销。自旋等待的时间或次数是有一个限度的,如果自旋超过了定义的时间仍然没有获取到锁,则该线程应该被挂起。

偏向锁:大多数情况下,锁总是由同一个线程多次获得。当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,偏向锁是一个可重入的锁。如果锁对象头的Mark Word里存储着指向当前线程的偏向锁,无需重新进行CAS操作来加锁和解锁。当有其他线程尝试竞争偏向锁时,持有偏向锁的线程(不处于活动状态)才会释放锁。偏向锁无法使用自旋锁优化,因为一旦有其他线程申请锁,就破坏了偏向锁的假定进而升级为轻量级锁。

轻量级锁:减少无实际竞争情况下,使用重量级锁产生的性能消耗。JVM会现在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针,成功则当前线程获取到锁,失败则表示其他线程竞争锁当前线程则尝试使用自旋的方式获取锁。自旋获取锁失败则锁膨胀会升级为重量级锁。

重量级锁:通过对象内部的监视器(monitor)实现,其中monitor的本质是依赖于底层操作系统的Mutex Lock实 现,操作系统实现线程之间的切换需要从用户态到内核态的切换,切换成本非常高。线程竞争不使用自旋,不会消耗CPU。但是线程会进入阻塞等待被其他线程被唤醒,响应时间缓慢。

在这里插入图片描述
[https://www.cnblogs.com/twoheads/p/10150063.html]

49.什么是死锁?

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

在这里插入图片描述

50.怎么防止死锁?

预防死锁
  这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

 避免死锁
  该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。(安全状态、银行家算法)

检测死锁
  这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,然后采取适当措施,从系统中将已发生的死锁清除掉。(死锁定理化简资源分配图)

解除死锁
  这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。(资源剥夺法,撤销进程法,进程回退法)

用两个线程请求被对方占用的资源,实现线程死锁

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

		ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
		1)实际的通过ThreadLocal创建的副本是存储在每个线程自己的threadLocals中的;
        2)为何threadLocals的类型ThreadLocalMap的键值为ThreadLocal对象,因为每个线程中可有多个threadLocal变量;
        3)在进行get之前,必须先set,否则会报空指针异常;
        如果想在get之前不需要调用set就能正常访问的话,必须重写initialValue()方法。

	    使用场景:
	    最常见的ThreadLocal使用场景为 用来解决数据库连接、Session管理等。

52.说一下 synchronized 底层实现原理?
http://www.vcchar.com/thread-28486-1-1.html
53.synchronized 和 volatile 的区别是什么?

54.synchronized 和 Lock 有什么区别?

55.synchronized 和 ReentrantLock 区别是什么?

56.说一下 atomic 的原理?

四、反射

57.什么是反射?

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

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

60.怎么实现动态代理?

五、对象拷贝

61.为什么要使用克隆?

62.如何实现对象克隆?

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

六、Java Web

64.jsp 和 servlet 有什么区别?

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

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

67.session 和 cookie 有什么区别?

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

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

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

71.如何避免 sql 注入?

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

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

七、异常

74.throw 和 throws 的区别?

75.final、finally、finalize 有什么区别?

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

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

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

八、网络

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

80.forward 和 redirect 的区别?

81.简述 tcp 和 udp的区别?

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

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

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

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

86.如何实现跨域?

87.说一下 JSONP 实现原理?

九、设计模式

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

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

十、Spring/Spring MVC

90.为什么要使用 spring?

91.解释一下什么是 aop?

92.解释一下什么是 ioc?

93.spring 有哪些主要模块?

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

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

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

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

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

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

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

101.spring mvc 有哪些组件?

102.@RequestMapping 的作用是什么?

103.@Autowired 的作用是什么?

十一、Spring Boot/Spring Cloud

104.什么是 spring boot?

105.为什么要用 spring boot?

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

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

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

109.jpa 和 hibernate 有什么区别?

110.什么是 spring cloud?

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

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

十二、Hibernate

113.为什么要使用 hibernate?

114.什么是 ORM 框架?

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

116.hibernate 有几种查询方式?

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

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

119.hibernate 是如何工作的?

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

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

122.hibernate 对象有哪些状态?

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

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

十三、Mybatis

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

126.mybatis 有几种分页方式?

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

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

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

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

131.mybatis 和 hibernate 的区别有哪些?

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

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

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

十四、RabbitMQ

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

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

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

138.rabbitmq 中 vhost 的作用是什么?

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

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

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

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

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

144.rabbitmq 有几种广播类型?

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

146.rabbitmq 集群有什么用?

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

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

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

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

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

十五、Kafka

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

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

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

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

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

十六、Zookeeper

157.zookeeper 是什么?

158.zookeeper 都有哪些功能?

159.zookeeper 有几种部署模式?

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

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

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

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

十七、MySql

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

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

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

167.说一下 ACID 是什么?

168.char 和 varchar 的区别是什么?

169.float 和 double 的区别是什么?

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

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

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

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

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

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

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

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

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

十八、Redis

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

180.redis 有哪些功能?

181.redis 和 memecache 有什么区别?

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

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

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

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

186.jedis 和 redisson 有哪些区别?

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

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

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

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

191.redis 如何做内存优化?

192.redis 淘汰策略有哪些?

193.redis 常见的性能问题有哪些?该如何解决?

十九、JVM

194.说一下 jvm 的主要组成部分?及其作用?

195.说一下 jvm 运行时数据区?

196.说一下堆栈的区别?

197.队列和栈是什么?有什么区别?

198.什么是双亲委派模型?

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

200.怎么判断对象是否可以被回收?

201.java 中都有哪些引用类型?

202.说一下 jvm 有哪些垃圾回收算法?

203.说一下 jvm 有哪些垃圾回收器?

204.详细介绍一下 CMS 垃圾回收器?

205.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

206.简述分代垃圾回收器是怎么工作的?

207.说一下 jvm 调优的工具?

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值