JavaSE面试题-有这一篇

JavaSE面试题

1、面向对象深刻理解?

面向对象就是对现实世界的具体存在的实体的抽象表述,这些对象在真实世界中都存在对应的实体,我们通过属性、行为来描述一个对象的存在状态。每一个对象都属一个类别,对象是这个类别的一个具体实例。在接解决问题时,先要从问题当中抽取出这些实例对象,描述这些对象在解决问题的过程中的行为和属性的变化过程,就是面向对象。

封装:将一个类别中的对象具有的属性、行为封装到一个类中,对外提供对应的方法来实现访问,隐藏了所有的实现细节

继承:可以使现有类拥有父类的所有功能,并可以实现对父类的功能的增强或重写,并且可以扩展出自己独有的功能。

多态:父类引用指向子类实现,同一个消息或行为在不同的子类实现中体现出不同的结果。

2、Java语言和其他语言区别?

Java存在jvm虚拟机,因此可以实现跨平台性,即一次编译,到处运行。

3、JRE、JDK、JVM区别?

Jdk是java开发工具包,其中包含了jre

Jre是Java的运行环境,其中包含了jvm和核心类库

Jvm是Java虚拟机, java运行时的环境,JVM是一种用于计算设备的规范

6、JDK1.8之前和JDK1.8之后接口不同?

Jdk1.8之前:红黑树

Jdk1.8之后:LocalDate、optional、流式api、函数式接口、lambda表达式、方法引用等。

7、接口和抽象类区别?

​ 接口通过interface修饰、一个类可以实现多个接口、实现了接口的类必须实现接口中的所有抽象方法、接口中除了default和static修饰的方法外都没有方法体。接口一般用来实现对方法的约束,制定规则。

​ 抽象类通过abstract修饰、一个类只能继承一个抽象类、继承了抽象类的类必须实现抽象类中的所有抽象方法,否则也必须声明为抽象的,抽象类中可以存在方法体,抽象类不能创建对象但是有构造方法。抽象类一般用于对公共部分的抽取,降低重复编码,提升效率。

8、Java中的常用容器有哪些?

数组:长度不可变、灵活性差、插入删除慢、读取快

集合:长度可变、灵活性高

Collection、和 Map

List:ArrayList和LinkedList、Vector

Set:HashSet、LinkedHashSet和TreeSet

Map:HashMap、LinkedHashMap、TreeMap和HashTable

9、线程和进程有什么区别?

​ 一个在内存中运行的应用程序就是一个进程、进程拥有自己独立的内存空间、它可以拥有多个线程,一个进程中的线程共享进程的堆和方法区,多线程可以并发运行,提升进程的运行效率。进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的最小单位

11、final、finally、finalize区别,怎么使用?

final是用来修饰类、方法和变量的。类上:不能被继承;方法上:不能被重写;变量上:不能被修改

finally:用来对异常进行处理时,无论如何都会被执行的代码段

finallize:是垃圾回收机制在回收对象之前调用该方法完成清除前的必要操作。

12、局部变量和成员变量区别?

​ 局部变量:声明在方法中,仅在最近的外层{}内有效

​ 成员变量:声明在类中,在该类中有效

13、值传递和引⽤传递区别?

​ 值传递:真实值(基本数据类型)

​ 引用传递:地址值(引用类型)

14、创建对象在JVM中的位置?

一般new出来的对象存储在堆内存中的新生代区域中、当该对象经历15次GC而未被回收后,将进入老年代中;

若new出的对象比较大时,将直接进入堆内存的老年代中,防止因为对象过大影响GC对新生代的垃圾回收性能。

15、==和equals区别?

​ Equals方法底层也是采用“ == ”的实现的;而对于基本数据类型而言比较的是真实值、对于引用类型而言比较的是地址值;

16、Hashcode和equals的区别?

​ Hashcode是用来生成对象的一个哈希值,不同对象的哈希值有可能会相同

​ Equals是用来对比两个对象是否相同,不同对象的equals方法返回false

即equals为true时哈希值一定相同,equals为false时哈希值有可能相同

17、重载和重写区别?

​ 重载是指在同一个类或子父类中存在方法名相同、方法的参数个数或参数类型不同的方法,在使用时可以通过传入的参数区分

​ 重写是指子类的方法和父类的方法定义完全相同,子类提供了自己的实现,因此父类的该方法被隐藏

18、Java基本数据类型?

​ Byte(1)、short(2)、int(4)、long(8)

​ Boolean(1/4)、char(2)、float(4)、double(8)

19、包装类和基本类区别?

​ 包装类:可为空、可以在泛型中使用、可以拥有诸多方法,效率低

​ 基本类:不可为空但有默认值、不能再泛型中使用、没有、高效

20、为什么要提供包装类?

​ 包装类可以通过该对象调用方法,可以拥有诸多的操作,而基本类无法调用方法,功能太弱

21、包装类和基础类怎么转换?

​ 基本类->包装类 自动装箱

​ 包装类->基本类 自动拆箱

22、构造器代码块、局部代码块、静态代码块执⾏顺序和执⾏次数?

​ 静态代码块:最先执行、仅一次

​ 构造代码块:每次构造方法之前、多次

​ 局部代码块:方法中、随方法执行、一次

23、构造代码块的作⽤?

​ 用于抽取出构造方法中的公共部分、减少重复代码

24、Integer是否可以被继承?为什么?

​ 不能,被final修饰

25、Integer缓存区间?什么时候触发缓存区间?

​ 当数据处于-128~127之间时(即占用一个字节时)、自动装箱时会触发缓存区间、用于节省内存和性能、即一个字节以内的数据采用缓存区间

26、"" 和 new String("")区别?

​ “”是在常量池中直接创建一个空串

​ New String(“”)则会在堆中创建一个对象,指向常量池中的空串

27、String、StringBuffer、StringBuild区别?是否线程安全?怎么做到线程安全?

​ String:使用final修饰的字符数组,不能被继承、不可变、不安全;实现了Serializable接口,可以序列化;实现了Comparable接口,可以比较大小;因为为了常量共享机制、所以设置为不可变。new String()默认创建了一个""串

String类进行

​ StringBuffer:可变、安全、效率低 ;使用synchronized加锁实现安全;new StringBuffer()默认创建16的数组;而new StringBuffer(“abc”),则使用"abc".length()+16,再使用父类的append()方法拼接;扩容为左移一位+2,2倍加2;

​ StringBuilder:可变、不安全、效率高;构造方法同StringBuffer,都是调用父类AbstractStringBuilder的方法。

28、包装类型、Math类常⽤的⽅法有哪些?在项⽬中怎么使⽤?

​ Integer、Long、Byte、Short、Float、Double、Character…

​ Math:ceil、floor、abs、max、min、round

30、&和&& | || 区别是什么?

​ 短路和不短路、&还可以作为位运算符与

31、JDK1.8之后有哪些新特性?

​ Lambda、函数式接口、流式接口、optional、方法引用、接口增加默认方法和静态方法、红黑树

32、Java中深克隆和浅克隆的区别?怎么实现?

​ Clonable接口中的clone方法实现、Serializable

​ 深克隆:对象的所有引用数据类型,以及引用的引用都被克隆

​ 浅克隆:仅克隆该对象、而该对象的引用数据类型未被克隆

33、Comparable 和Comparator的区别,分别说出使⽤场景?

​ Comparable接口中的comparableTo方法一般由类实现、当这个实现不能满足要求时,可以采用Comparator中的compare方法来实现、因此当两者同时存在时、Comparator的优先级较高

34、Object类和范型的区别,说出范型的执⾏机制,为什么要使⽤范型?

​ Object:Object需要进行强制类型转换易出现类型转换异常、

​ 泛型:将运行时错误提前到编译期解决

35、Collection 和Collections 的区别?

​ Collection是单列集合的顶层接口

​ Collections是针对这些集合的工具类,提供了操作这些集合的方法

36、HashMap 和Hashtable 的区别?

​ HashMap不安全、高效;初始空间16,扩容为二倍;迭代器使用Iterator;支持null(key);哈希算法位运算

​ HashTable安全、效率低,底层使用synchronized实现,但是是为整个数组加锁,因此效率太低;初始空间11,扩容二倍+1;迭代器使用Enumeration;不支持null(key、value);哈希算法取余算法;

​ 等同于Collections.synchronizedMap(Map map);也是对整张hash表加锁。

​ ConcurrentHashMap:安全、高效;使用Lock接口的实现类ReentrantLock实现,但是加锁的是单独的一个链表,效率有所提升。采用写时复制、读写分离,采用private transient volatile Object[] array,实现数据可见性。

37、HashMap是线程安全的吗?如何得到一个线程安全的HashMap?

​ 不安全、使用Collections的synchronizedHashMap方法

38、如何解决Hash冲突问题?

​ 采用合适的加载因子和哈希算法来减少冲突、使用链表红黑树存储冲突的数据、二次哈希法、

39、HashMap是如何实现自动扩容的?

​ Jdk8中当第一次存入数据时,底层创建一个16的Node[]、当存储的元素数量/数组长度>=加载因子0.75时,即扩容为原来的2倍、是因为容量是2的n次幂,可以使得添加的元素均匀分布在HashMap中的数组上,减少hash碰撞,避免形成链表的结构,使得查询效率降低!

​ 当某一条链表上的元素个数大于8时,此时若数组长度还没有大于64,则也会进入自动扩容。

扩容后需要将原来的数据拷贝到新的数组中。

40、HashMap的底层原理?

​ 1.8中创建hashmap时,不会创建数组,当第一次插入数据时会创建一个16的Node[]数组;

​ 当存入数据时,会根据数据的key的hashcode使用散列函数进行计算获得该数据在数组中的索引值:

当该索引处没有数据时,直接插入该索引处即可

当该索引处有数据时,判断两个数据的key的hashcode是否相同

​ 当hashcode不相同时,则认为两个对象不同,将数据存入该索引的链表

​ 当hashcode相同时,判断equals方法

​ 当equals方法为false,则不同,将数据存入链表中

​ 当equals方法为true,则相同,使用新的value替换旧的value

此时插入操作结束。

当插入时该链表上的节点个数大于等于8时,会判断数组长度是否大于等于64:

​ 当数组长度小于64,则应当扩容

​ 当数组长度大于等于64,应当将该链表修改为红黑树

扩容:1.当集合元素个数/数组长度>=加载因子0.75时,扩容

​ 2.当某个链表长度大于等于8,且数组长度小于64,扩容

41、List和set的区别?

​ List:可以存储相同的数据、

​ Set:必须实现equals方法、不能存储相同的数据

42、ArrayList和LinkedList的区别?

​ ArrayList:使用Object[]存储、查询快;jdk7中new ArrayList()底层创建一个10的数组,原长+左移一位,扩容为原来的1.5倍;jdk8中new ArrayList()创建空数组,第一次add时创建10数组;

​ LinkedList:采用带有头尾指针的双向链表存储、插入删除快;使用Node存储数据,item、next、prev三个值

43、线程创建4种方式?

​ 1.继承Thread类,重写run方法

​ 2.实现Runnable接口实现run方法

​ 3.实现Callable方法实现call方法,有返回值

​ 4.采用线程池:new ThreadPoolExecutor(7个参数)创建线程:核心线程数、最大线程数、空闲线程存活时间、时间单位、阻塞队列、创建线程的工厂、超出任务拒绝策略;

超出任务拒绝策略:

ThreadPoolExecutor.Abortpolicy 丢弃任务,并抛出异常,默认策略

ThreadPoolExecutor.DiscardPolicy 丢弃任务,不抛出异常

ThreadPoolExecutor.DisOldestPolicy 丢弃等待时间最久的任务,把当前任务加入等待队列

ThreadPoolExecutor.CallerRunsPolicy 调用任务的run()方法绕过线程池执行。

44、并发和并行有什么区别?

​ 并发:多个线程在某一个时间段内,交替执行,单cpu

​ 并行:多个线程在某一时刻同时运行,多cpu

44、为什么要使用线程池?

​ 因为线程的创建和销毁会占用大量系统资源、因此过多的创建和销毁操作会使系统的性能减低,因此采用线程池预先创建一定数量的线程,在需要时直接使用,使用完毕后,又放回线程池中,减少了运行过程中的性能开销

45、线程池的构造方法里几个参数的作用分别都是什么?

​ 核心线程数量、最大线程数量、空闲线程存活时间、存活时间单位、阻塞队列、创建线程的工厂、超出的任务拒绝策略。

46、什么是线程安全问题?(从单线程和多线程两个方向说)

​ 在单线程中,我们对一个数据的修改不会发生数据不一致的错误,因为这个数据只被一个线程持有

​ 当多线程中,多个线程操作同一个数据时,会发生多个线程同时修改同一个数据,从而导致多个线程修改的结果失效,出现数据安全问题

47、如何解决线程安全问题?

​ 采用synchronized或lock锁对共享变量进行独占式访问

​ 或采用cas无锁编程的方式

48、线程的生命周期?

​ 创建态:创建完毕调用start进入就绪态

​ 就绪态:获得cpu执行权进入运行态

​ 运行态:线程执行结束进入结束态 或 运行过程中发生阻塞进入阻塞态

​ 阻塞态:阻塞状态结束进入就绪态,等待cpu

​ 结束态:销毁线程

49、JAVA中可以冻结线程的两个方法及区别?

​ Sleep:使线程进入阻塞状态,不释放锁,释放cpu执行权

​ Wait:使线程进入阻塞状态,释放锁,释放cpu执行权

50、notify()和 notifyAll()有什么区别?

​ Notify:随机通知一个被冻结的线程

​ NotifyAll:通知所有被冻结的线程,开始抢占式获取cpu的执行权

51、请说出sql语句中 left join ,inner join 和right join的区别?

​ Left join: 左外连接,当右边的表没有对应的行时,为null,同时去掉左表没有的数据行

​ Inner join: 内连接,左右两表按照属性拼接,仅对应属性同时拥有的行

​ Right join: 右外连接,当左边的表没有对应的行时,为null,同时去掉右表没有的数据行

​ left join的效率最高。

52、讲一下JDBC流程?

​ 1.使用Class类加载对应的驱动程序

​ 2.使用DriverManager.registerDriver注册驱动

​ 3.创建Connection连接

​ 4.使用Statement或PreparedStatement执行或预编译sql语句

​ 5.使用ResultSet和ResultSetMetaData处理结果

​ 6.关闭connection连接

53、数据库连接池的工作机制?

​ 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

54、Java 中常用的设计模式?说说工厂模式或者几种比较熟悉的说一下?

​ 工厂模式:将创建对象的操作集中起来放在一个类中,当需要某一个对象时,直接从该类中获取,这个进行统一生成对象的类就是工厂类,这种获取对象的方式就是工厂模式。

​ 单例模式:当某一个类,仅允许存在一个实例对象时,即符合单例模式

​ 饿汉式:在类加载的时候就将对象创建出来,使用时直接返回

​ 懒汉式:在第一次使用时才创建实例对象,可能会出现安全问题

​ 双端检锁+禁止指令重排

​ 内部类

​ 装饰者模式:在不改变原有类的情况下对原有类进行功能的扩充(需要实现同一个接口),装饰类需要和被装饰类实现同一个接口,并且装饰类中需要一个被装饰类的引用,来调用被装饰类的原有方法。

55、char 型变量中能不能存储一个中文汉字?为什么?

​ 一个char变量占用两个字节,Unicode编码固定采用2字节,所以可以

56、error 和exception 有什么区别?

​ Error是系统运行出现了错误,是属于系统硬件层面的问题

​ Exception是异常,是代码的缺陷,可以通过修改代码来解决

57、TCP与UDP的区别?

TCP:面向连接的、速度慢、传输的数据大小无限制;先建立连接,确保连接无误才进行数据传输,数据传输完毕,需要断开连接。通常用于上传下载文件。

​ UDP:面向用户的、速度快、传输的数据最大64K;发送端和接收端无需建立连接;通常用于视频通话,可以允许丢包。UDP存在三种模式:单播、组播、广播

三次握手:

第一次握手:客户端向服务器端发送一个SYN标志位,代表客户端想要与服务器端建立连接。

第二次握手:服务器端接收到请求后,响应SYN和ACK标志位;ACK=1为请求确认表示收到数据,并指定下一次客户端的发送数据序列号Seq=1;

第三次握手:客户端向服务器端发送ACK和Seq=1,ACK=1表示客户端期待服务器端的下次数据的序列号为1;而Seq=1为服务器端所期望的数据序列号。此时连接建立成功,

四次挥手:

第一次挥手:客户端发送FIN、ACK,表示客户端要断开连接了;ACK=1表示期待服务器端的响应数据序号Seq=1

第二次挥手:服务器端发送ACK、Seq;Seq=1为客户端的期望数据流序号,ACK=2表示期待下一次客户端的数据序号为2,若客户端还有数据未发送完可以此时继续发送。

第三次挥手:服务器端再次向客户端发送FIN,ACK,告知服务器端关闭连接了,Seq=1就是客户端想要的数据序列号。ACK=2表示希望客户端的数据序号为2

第四次挥手:客户端向服务器端发送ACK、Seq,告知服务器端已收到服务器端的关闭信息,Seq=2表示就是服务器端希望的数据序号

58、int 和Integer 有什么区别?

​ Int是基本数据类型,不能为null,不能调用方法

​ Integer是引用类型,可以为null,可以调用方法

image

59、并行和并发有什么区别?

​ 略

60、线程和进程的区别?

​ 略

61、什么是反射?

反射(Reflaction)是指在程序运行过程中动态的获取某一个类或对象的字节码,通过对字节码的解析可以动态获取该类或对象的详细信息如:类的属性、方法、实现的接口等,调用对象的属性方法等。创建该类的对象、也可以修改某一个对象的属性等信息。

62、什么是 Java 序列化?什么情况下需要序列化?

序列化是指将Java对象按照一定的方式转换成和平台无关的二进制数据,从而实现在网络中传输或实现持久化,接收方只需要按照同样的方式解析,就可以得到该Java对象,实现反序列化。

当我们需要将对象写入磁盘或在网络中传输时,需要使用序列化

63、动态代理是什么?有哪些应用?

为目标对象提供一个代理对象,由代理对象控制目标对象的引用;也就是目标对象的所有方法调用都会进入代理对象的控制器中。从而实现在不改变原有代码的情况下实现对原有方法的增强。

AOP、

64、怎么实现动态代理?

底层是通过反射实现的,jdk动态代理采用Proxy类中的静态方法newProxyInstance方法实现代理对象的创建,其中被代理的对象必须实现一个接口,该静态方法的实现需要被代理类的类加载器被代理类实现的接口处理器这三个参数

底层通过反射创建一个和目标类实现同一个接口的代理对象,由代理对象控制目标的引用,也就是目标对象的所有方法调用都会进入代理对象的控制器中。从而实现在不改变原有代码的情况下实现对原有方法的增强。

65、如何复制一个文件夹,通过递归的方式?(说实现思路加伪代码)
public void copyFileRecur(File file) {
	if(file.isFile()) 创建一个文件
    if(file.isDirectory()) {
        创建一个文件夹
       	for(file.getFileList():f){
            copyFileRecur(f);
        }
    }
}
1.该递归方法需要一个file对象
    1.该file对象是一个文件,直接创建一个文件
    2.该file对象是一个文件夹,先创建一个文件夹,然后遍历其中所有的文件和文件夹,递归调用自身
递归结束条件:传入的文件是一个对象。
66、说一下 JVM 的主要组成部分?及其作用?JVM调优?

类加载器子系统:通过一系列的方式把字节码文件加载到运行时数据区中的方法区中

运行时数据区:Java虚拟机栈、堆、方法区(逻辑上属于堆)、本地方法栈、程序计数器

执行引擎:用来将指令集翻译为机器语言

本地库接口:用于调用一些本地方法

67、说一下堆栈的区别?

堆:存放对象的、线程共享的、

栈:存放局部变量的、线程私有的

68、什么情况下会出现堆内存溢出?

内存不足、对象使用不合理gc未及时回收垃圾

69、什么是类加载器?及类加载器的分类?

用来将字节码文件加载到内存中的工具

启动类加载器、平台类加载器、系统类加载器、用户类加载器

70、说一下类加载的执行过程?

**加载阶段:**将这个类加载到内存中,创建一个Class对象

验证:确保Class字节码文件中包含的信息符合当前虚拟机的规范,不会危害虚拟机的自身安全

准备:为该类中的类static变量分配内存、设置默认值==初始化静态变量

解析:将类的二进制流中的符号引用替换为直接引用 :链接阶段

**初始化阶段:**根据代码去执行初始化类变量和其它资源

71、什么是JAVA里双亲委派机制?

​ 当一个类加载器收到了一个类加载请求,它会把这个请求委托给父类加载器去执行、父类加载器同样会委托给自己的父类加载器,直到达到顶层类加载器;若父类加载器能够完成加载的任务,则成功并返回;若父类加载器无法单独完成加载,则会向下调用子类加载器去完成,这个类加载的过程就是双亲委派模型

为什么会出现双亲委派模型?

防止内存中出现多份同样的字节码,这样类的唯一性将无法保证。

若是存在一个类需要被加载到内存中,用户类使用自己的加载器去加载,就会发生每个用户都加载了一份该类的字节码,这就违反了类的唯一性。

72、怎么判断对象是否可以被回收?

通过jvm的垃圾回收算法判断的

  1. **引用计数法:**记录一个对象的引用数,当引用数为0时,jvm认为该对象是垃圾,可以被回收;无法解决对象之间的循环引用问题而被淘汰。

  2. **可达性分析算法:**这种算法中存在一系列的GC Roots对象,以这些对象为起点向下搜索,所走过的路径称为引用链,凡是这些GC Roots对象无法到达某个对象时,则标记该对象为不可用的,但是,不一定回收

    在Java语言中,可作为GC Roots的对象包括下面几种:

    虚拟机栈(栈帧中的本地变量表)中引用的对象。
    方法区中类静态属性引用的对象。
    方法区中常量引用的对象。
    本地方法栈中JNI(即一般说的Native方法)引用的对象。

    此时,它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当没有被finallize()方法覆盖或已经执行过,则认为没有必要执行,可以直接被回收

    若此时认为有必要执行finallize()方法,则会将该对象放入一个队列中等待执行finallize()方法。若在执行该方法时,它与引用链产生关联,则在jvm第二次标记时不会被回收。

  3. 回收方法区:回收废弃常量和无用类

    判定一个类是否是“无用的类”的条件苛刻许多。需要同时满足下面的三个条件:

    该类的所有实例已经被回收,也就是Java堆中不存在该类的任何实例
    加载该类的ClassLoader已经被回收
    该类对应的class对象已经被回收,无法在任何地方通过反射访问到该类的方法

    引用计数法和可达性分析算法都是针对堆内存的、回收方法区是针对方法区的

73、说说垃圾回收算法的底层原理?(新生代、老年代)

​ 堆内存:新生代、老年代、持久代

​ 1.新生代:edensurvivor fromsurvivor to

​ 新创建的对象一般都被放在新生代的eden区域中。

​ 2.老年代:在新生代中被多次GC,但没有被回收时,达到15次时,进入老年代;或一些大的对象不经过新生代,直接进入老年代

​ 3.持久代:存储class、method元信息

标记-清除算法:被标记后直接清除,会带来内存碎片化问题,当出现较大对象时,无法分配内存,则会再次触发垃圾回收。

复制算法:Java堆中的新生代的垃圾回收算法。解决了内存碎片化问题;首先标记待回收内存和不回收内存,将不回收内存数据复制到新的内存中,并回收旧内存区域所有内存,此时旧内存区域就是连续可用的。经历一次复制算法没被回收,则年龄+1,15岁时进入老年代。

标记-压缩算法:老年代的垃圾回收算法。标记-压缩算法首先还是“标记”,标记过后,将不用回收的内存对象压缩到内存一端,此时即可直接清除边界处的内存。这样就能避免复制算法带来的效率问题,同时也能避免内存碎片化的问题。

老年代为什么不使用复制算法:对于新生代,大部分对象都不会存活(二八定律),所以在新生代中使用复制算法较为高效,而对于老年代来讲,大部分对象可能会继续存活下去,如果此时还是利用复制算法,效率则会降低。

74、什么是死锁?怎么防止死锁?

死锁是指在多线程环境中,线程拥有了一个的排他锁,同时又去获取另一个排他锁;但是,这个锁被另一个线程所拥有,并且这个线程也在尝试获取另一个锁,此时每个线程都持有一把锁,同时也在等待另一个锁,这个时候就陷入了无限等待中… 这个状态就是死锁。

避免重复获取锁、无锁并发编程CAS算法

75、哈希冲突的解决方式有几种?
  1. 开放寻址法:线性探测法、平方寻址法
  2. 拉链法:采用数组+链表
  3. 二次哈希:对哈希值再次进行哈希算法
  4. 采用基本表+溢出表:将冲突元素存入溢出表

**基础:**多线程(创建方式、睡眠、唤醒、锁机制、并发处理、无锁并发)、JVM(优化、执行顺序、类加载器(双亲委托机制))、GC(新生代、老年代相互转换、可达性分析算法、引用计数器算法、f\f\f)、设计模式(3~5)、简单算法、集合(List(优化)\得到线程安全、Map(底层原理、自动扩容、hash碰撞解决) 、反射、IO

数据结构、算法分析

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值