1. java arraylist和linkedlist存储结构的区别?这两个结构是线程安全的吗?
arraylist内存连续,随机访问性能高,插入和删除比linkedlist慢;
linkedlist内存不连续,随机访问性能比arraylist低,插入和删除元素性能高;
这两个结构都是线程不安全的,多线程环境下使用应该加同步措施;
2. hashmap put的过程?hashmap的容量为什么一直是2的n次方?
put的过程:计算出哈希值,找到对应的位置,检查该位置是否有元素,如果没有,或者该位置的元素的key与要插入的元素的key相同,则直接插入元素或更新value,如果有则通过链表或者红黑树的方式解决冲突;
采用2的n次方作为容量,使得在计算元素索引时,可以直接通过对哈希值进行位与操作(hash & (length-1))得到,这比模运算(hash % length)更高效;
3. 讲讲final关键字?能修饰抽象类吗?
final修饰类,表示该类不能被继承;
final修饰方法,表示该方法不能被重写;
final修饰变量,表示该变量不能被改变;
final修饰引用,表示该引用不能被改变,引用指向的对象可以改变;
final不能修饰抽象类,因为抽象类只能被继承
4. 抽象类一定要有抽象方法吗?抽象类可不可以全都是普通方法?
不一定,抽象类可以全是普通方法,但是有抽象方法的类一定要声明成抽象类
5. 线程池的核心参数有哪些,每个参数的作用都讲一下?举个例子解释一下这些参数?
核心线程数:线程池中的最小线程数;
最大线程数:线程池能包含的最大线程数,当执行任务的线程大于等于核心线程数且小于最大线程数,这时提交一个任务会生成一个新的线程来执行这个任务;
生存时间:当线程数超过核心线程数时,如果有线程的空闲时间(即没有执行任务的时间)超过了生存时间,该线程就会被销毁;
生存时间单位:生存时间的时间单位,ms/ns
线程工厂:可以在构造方法中传入一个线程工厂用来生成线程
6. 讲讲JVM类加载过程
1.加载:查找并加载类的字节码文件,类加载器根据类的全限定名称加载类的字节码文件
2.验证:对查找到的字节码文件进行验证,确保加载的字节码文件是合法的符合规范的。包括文件格式验证、元数据验证、字节码验证、符号引用验证等步骤。
3.准备:为类的静态变量分配内存并设置初始值
4.解析:把符号引用变为直接引用,由于在文件中没有地址这个概念,此时的引用是一个类似偏移量的值,就叫做符号应用。
7. 讲讲双亲委派机制
jvm中提供了三种类加载器:
启动类加载器:负责加载Java标准库中的类
扩展类加载器:负责加载Java的扩展类库,位于jre/lib/ext目录下的类库
应用程序加载器:负责当前项目的目录以及第三方库类的加载
这个三个加载器存在一种“父子关系”, 前面为父后面为子。
当一个类加载器收到类加载请求时,不会立刻开始类加载,而是把这个请求交给他的父加载器,直到交给启动类加载器,如果启动类加载器无法加载该类(搜索目录中没有该类),则会交给扩展类加载器,再无法加载则会交给应用程序类加载器,再无法加载则会抛出ClassNotFoundException异常。
上述流程保证了加载类的顺序,防止用户自定义的类替换掉Java库中的类
8. 慢sql有什么优化思路?
尽量减少使用 SELECT *,只选择需要的列。
避免在 WHERE 子句中使用函数操作或表达式对索引列进行计算,这可能导致索引无法使用。通过分页限制返回的行数,避免一次性处理大量数据。
确保在经常用于查询、连接、排序和分组的列上创建合适的索引。
9. 慢sql有没有什么评判标准?
响应时间阈值:根据业务需求和用户体验,设定一个固定的响应时间阈值。例如,如果一个查询的平均响应时间超过 2 秒被认为是慢的。
与历史性能对比:如果当前 SQL 的执行时间明显长于过去相同或相似查询的执行时间,那么可能被视为慢 SQL。
业务影响:如果 SQL 的执行导致业务流程出现卡顿、阻塞或影响了其他关键操作的正常进行,即使响应时间在某些标准下不算长,也可能被认定为慢 SQL。