赞
踩
接口和抽象类的区别
(1)抽象类可以有构造方法
,而接口没有
(2)抽象类可以有抽象方法
和普通方法
,接口只能有抽象方法
(3)抽象类的成员4种权限修饰符都可以修饰,接口只能用private
java权限修饰符有哪些
接口重载和重写的区别
final
和private
修饰的方法不可重写== 和 equals的区别
基本类型
来说是值比较,对于引用类型
来说是比较的是内存地址;默认
情况下是引用比较,只是很多类重写
了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。异常处理机制
(1)使用try、catch、finaly捕获异常,finaly中的代码一定会执行,捕获一场后程序会继续
执行
(2)使用throws声明该方法可能会抛出
的异常类型,出现异常后,程序终止
HashMap的原理
key不能重复
,可以为null
,线程不安全16
,默认的负载因子为0.75
,当HashMap中的元素个数超过临界值时,就会创建一个大小为前一次2倍
的新数组,再将原来数组中的数据复制
到新数组中。当数组长度大于64
且链表长度大于8
时,链表转为红黑树hash
,根据二次hash
结果找到对应的索引位置equals
比较,若结果为true说明key相同则取代该元素,若结果为false,就使用高低位平移
将节点插入链表(JDK8
以前使用的是头插法
,但是头插法在并发扩容时可能会造成环形链表
或数据丢失
; 而高低位平移发会发生数据覆盖
的情况)想要线程安全的HashMap怎么办
(1)使用ConcurrentHashMap
(2)使用HashTable
(3)Collections.synchronizedHashMap()方法
ConcurrentHashMap原如何保证的线程安全
分段锁
,将一个Map分为了16个段,每个段都是一个小的hashmap,每次操作只对其中一个段加锁CAS+Synchronized
保证线程安全,每次插入数据时判断在当前数组下标是否是第一次插入,是就通过CAS方式插入,然后判断f.hash是否=-1,是的话就说明其他线程正在进行扩容,当前线程也会参与扩容;删除方法用了synchronized修饰,保证并发下移除元素安全HashTable与HashMap的区别
(1)HashTable的每个方法都用synchronized修饰,因此是线程安全的,但同时读写效率很低
(2)HashTable的Key不允许为null
(3)HashTable只对key进行一次hash,HashMap进行了两次Hash
(4)HashTable底层使用的数组加链表
ArrayList和LinkedList的区别
ArratList
10
,当元素数量到达容量时,生成一个新的数组,大小为前一次的1.5
倍,然后将原来的数组copy过来LinkedList
如何保证ArrayList的线程安全
(1)使用collentions.synchronizedList()方法为ArrayList
加锁
(2)使用Vector,Vector底层与Arraylist相同,但是每个方法都由synchronized
修饰,速度很慢
(3)使用juc下的CopyOnWriterArrayList,该类实现了读操作不加锁
,写操作时为list
创建一个副本,期间其它线程读取的都是原本list
,写操作都在副本中进行,写入完成后,再将指针指向副本。
String、StringBuffer、StringBuilder的区别
String
和 StringBuffer
、StringBuilder
的区别在于 String
声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder
可以在原有对象的基础上进行操作,所以在经常改变
字符串内容的情况下最好不要使用 String。进程和线程的区别
进程:系统运行的基本单位,包含多个线程
线程:独立运行的最小单位,是进程的实体,多个线程共享同一进程内的系统资源
什么是线程上下文切换
当一个线程被剥夺cpu使用权时,切换到另外一个线程执行
什么是死锁
死锁指多个线程在执行过程中,因争夺资源造成的一种相互等待的僵局
死锁的必要条件
只能
由一个线程读取不能
强行剥夺线程占有的资源同时
对自己手中的资源保持
不放相互
等待资源的过程中,形成一个闭环Synchrpnized和lock的区别
(1)synchronized是关键字,lock是一个类
(2) synchronized在发生异常时会自动释放锁,lock需要手动释放锁
(3)synchronized是可重入锁、非公平锁、不可中断锁,lock是可重入锁,可中断锁,可以是公平锁
sleep()和wait()的区别
yield() 和 join()区别
线程池七大参数
Java内存模型
一致
的内存访问效果,它定义了JVM如何将程序中的变量在主存中读取独有
的工作内存,线程想要操作变量必须从主
从中copy变量到自己的工作区,每个线程的工作内存是相互隔离
的不是
原子性操作,所以会有线程安全问题保证并发安全的三大特性?
不被
其他线程影响立刻
知道顺序
改变,有序性是禁止
指令重排volatile
保证
变量的可见性和有序性,不保证
原子性。使用了 volatile 修饰变量后,在变量修改后会立即同步
到主存中,每次用这个变量前会从主存刷新。线程使用方式
ThreadLocal原理
threadLocal
实例,value为要保存的副本。内存泄露
问题,因为key为弱
引用,而value为强
引用,每次gc时key都会回收
,而value不会被回收
。所以为了解决内存泄漏问题,可以在每次使用完后删除value或者使用static
修饰ThreadLocal,可以随时获取valueThreadLocal 的经典使用场景是数据库连接和 session 管理等。
什么是CAS锁
只能
支持一个变量的原子操作,不能
保证整个代码块的原子操作JUC常用辅助类
CountDown()
时数量减一,当调用await()
时判断计数器是否为0,不为0就阻塞,直到计数器为0await()
时判断计数器是否达到目标值,未达到就阻塞,直到计数器达到目标值acquire()
时判断是否还有信号,有就信号量减一线程继续执行,没有就阻塞等待其他线程释放信号量,当调用release()
时释放信号量,唤醒阻塞线程如何根据 CPU 核心数设计线程池线程数量
JVM运行时数据区
新生代
和老年代
存放类信息、静态变量、常量、运行时常量池
等信息。JDK1.8之前用持久代
实现,JDK1.8后用元空间
实现,元空间使用的是本地内存,而非在JVM内存结构中什么情况下会内存溢出
不停的创建
而不被回收时JVM有哪些垃圾回收算法
复制
到另一块区域,然后清空之前的区域。用在新生代
向一端移动
,然后清除边界外的垃圾对象。用在老年代
GC如何判断对象可以被回收
引用计数器
,引用为0
时判定可以回收;这个可能会出现两个对象相互引用无法回收的问题GCRoot
开始往下搜索,搜索过的路径称为引用链
,若一个对象GCRoot没有任何的引用链,则判定可以回收典型垃圾回收器
G1 :JDK1.9以后的默认垃圾回收器,支持并发,采用标记整理+复制算法,注重响应速度
类加载器和双亲委派机制
从父类加载器到子类加载器分别为:
还有一个自定义类加载器
当一个类加载器收到类加载请求时,会先把这个请求交给父类加载器处理,若父类加载器找不到该类,再由自己去寻找。该机制可以避免类被重复加载,还可以避免系统级别的类被篡改
类加载过程
静态变量
和常量
转换到方法区
,在堆中生成class
对象作为方法区入口正确性
设置
初始值符号引用
解析为直接
的一个引用(类在实际内存中的地址)赋值
并初始化
静态代码块JVM中有哪些引用
强引用:new的对象。哪怕内存溢出也不会回收
软引用:只有内存不足时才会回收
弱引用:每次垃圾回收都会回收(例如:ThreadLocal中的key)
虚引用:必须配合引用队列使用,一般用于追踪垃圾回收动作
对象头中有哪些信息
对象头中有两部分,一部分是MarkWork,存储对象运行时的数据,如GC
分代年龄、GC
标记、锁的状态、线程ID等;另外一部分是指向对象类型的指针,如果是数组,还有一个部分存放数组长度
JVM内存参数
-Xmx[]: 堆空间最大内存
-Xms[]: 堆空间最小内存,一般设置成跟堆空间最大内存一样的
-Xmn[]: 新生代的最大内存
-xx[use 垃圾回收器名称]:指定垃圾回收器
-xss: 设置单个线程栈大小
一般设堆空间为最大可用物理地址的百分之80
JVM类初始化顺序
父类
静态代码块和静态成员变量->子类
静态代码块和静态成员变量->父类
代码块和普通成员变量->父类
构造方法->子类
代码块和普成员变量->子类
构造方法
MyIAm和InnoDB的区别
InnoDB支持事务,MyIAm不支持
InnoDB支持外键,MyIAm不支持
InnoDB是聚簇索引,MyIAm是非聚簇索引
InnoDB支持行锁和表锁,MyIAm只支持表锁
InnoDB不支持全文索引,MyIAm支持
InnoDB支持自增和MVCC模式的读写,MyIAm不支持
Mysql事务特性
原子性:一个事务内的操作要么成功
要么失败会滚
,不存在中间状态
一致性:事务前后的数据总量不变,也就是说一个事务执行之前和执行之后都必须处于一致性
状态
隔离性:是指多个事务并发执行的时候,事务与事务之间相互不影响
持久性:事务一旦提交发生的改变不可逆
的,即便是在数据库系统遇到故障的情况下也不会丢失
提交事务的操作
事务靠什么保证
undolog
日志保证,他记录了需要回滚的日志信息,回滚时撤销已执行的sqlMVCC
保证redolog
日志和内存
保证,mysql修改数据时内存和redolog
会记录操作,宕机时可恢复事务的隔离级别
在高并发情况下,并发事务会产生脏读
、不可重复读
、幻读
问题,这时需要用隔离级别来控制
1、脏读
出现原因:一个事务读取到了缓存中另一个事务未提交的脏数据。
(说明:当事务B对data进行了修改但是未提交事务,此时事务A对data进行读取,并使用事务B修改的数据做业务处理。)
2、幻读
出现原因:一个事务在读取数据时,另一个事务插入了数据,导致上个事务第二次读取数据时,数据不一致。
(说明:data 表有一条数据,事务A对data进行读取, 事务B对data进行数据新增 ,此时事务A读取只有一条数据,而最后实际data是有两条数据,就好象发生了幻觉一样情况成为幻读)
3、不可重复读
出现原因:读取数据的同时可以进行修改
(说明:事务A、事务B同时对data进行访问,事务A对data进行读取,事务B对data进行修改,当事务A第一次对data进行读取完后事务B提交,此时当事务A第二次读取该数据时的数据就与第一次读取的数据不同,这种情况称为不可重复读)
读未提交
):可读取未提交事务的操作数据,最低的隔离级别,一般都没有用的。这种情况会出现脏读。读已提交
):一个事务等另一个事务提交之后才可进行读取,解决了脏读问题,但会出现不可重复读可重复读
):读取事务开启的时候不能对数据进行修改,解决了不可重复读问题,但是存在幻读问题序列化
):是最高的事务隔离级别,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用什么是快照读和当前读
快照读
:读取的是当前数据的可见版本,可能是会过期数据,不加锁的select就是快照读当前读
:读取的是数据的最新版本,并且当前读返回的记录都会上锁,保证其他事务不会并发修改这条记录。如update、insert、delete、select for undate(排他锁)、select lockin share mode(共享锁) 都是当前读MVCC是什么
MVCC是多版本并发控制,为每次事务生成一个新版本数据,每个事务都由自己的版本,从而不加锁就决绝读写冲突,这种读叫做快照读。只在读已提交和可重复读中生效。
实现原理由四个东西保证,他们是
MySQL有哪些索引
不能有空值
和重复值
不能有相同值
,但允许为空
多个字段
建立一个联合索引
,减少索引开销
,遵循最左匹配
原则倒排索引
提升检索效率,广泛用于搜索引擎聚簇索引和非聚簇索引的区别
他们都是b+数
结构
B和B+数的区别,为什么使用B+数
极端情况会变成链表
形式高度不可控
索引值
和data
都分布在每个具体的节点
当中,若要进行范围查询,要进行多次回溯
,IO开销大非叶子节点
只存储索引值
,叶子节点
再存储索引
+具体数据
,从小到大用链表连接在一起,范围查询可直接遍历不需要回溯MySQL有哪些锁
基于粒度:
基于属性:
MySQL如果做慢查询优化
哪些情况索引会失效
Mysql内连接、左连接、右链接的区别
交集
部分。select * from A a inner join B b on a.id=b.id
select * from A a left join B b on a.id=b.id
select * from A a right join B b on a.id=b.id
Bean的作用域
IOC
容器只有一个getBean()
都会生成一个新的对象http
请求都会创建一个自己的beansession
共享一个实例serverContext
只有一个beanwebsocket
只有一个beanBean的生命周期
如果没有配置后置处理器,bean的生命周期将没有3和5
Spring 事务原理
spring事务有编程式和声明式,我们一般使用声明式,在某个方法上增加@Transactional
注解,这个方法中的sql
会统一成功或失败
@Transactional
注解,spring会基于这个类生成一个代理对象并将这个代理对象作为bean,当使用这个bean中的方法时,如果存在@Transactional
注解,就会将事务自动提交设为false,然后执行方法,执行过程没有异常就会提交,有异常就会回滚spring事务失效场景
public
类型rollbackfor
属性设置spring事务的隔离级别
default
:默认级别,使用数据库自定义的隔离级别
其它四种隔离级别与mysql一样
spring事务的传播行为
required
:(默认传播行为),它是Spring里面默认的事务传播行为,也就新当前存在事务就加入到当前事务去执行,如果不存在事务就创建一个事务requires_new
:它不管是否存在事务,它都会新开启一个事务来执行,新老事务相互独立的,外部事务抛出异常,并不会影响内部事务的一个正常提交supports
:表示支持当前的事务,如果当前不存在事务,就以非事务的方式去执行mandatory
:它是一个强制的事务执行,如果当前不存在事务就抛出一个异常not_supported
:表示以非事务的方式来运行,如果当前存在事务,就需要把当前的事务挂起来。never
:就是以非事务执行,如果存在事务,抛出异常。nested
:如果当前存在事务,就嵌套当前事务中去执行,如果当前没有事务,那么就新建一个事务,类似 requires_new这个样一个传播行为Spring IoC
IOC(Inversion of Control 即控制反转)将对象交给容器管理
我们要考虑:谁控制谁控制什么?为了是反转?哪些方面反转?
容器
控制了对象
外部资源
及生命周期
spring中提供了一种IOC容器,来控制对象的创建,无论是你创建对象,处理对象之间的依赖关系,对象的创建时间还是对象的创建数量,都是spring提供IOC容器上配置对象的信息就可以了。
IOC能做什么
: 由IOC容器帮对象找相应的依赖思想并注入,并不是由对象主动去找资源集中管理,实现资源的可配置和易管理降低了使用资源双方的依赖程度,解耦合
spring用了哪些设计模式
springboot常用注解
@RestController :修饰类
,该控制器会返回Json
数据
@RequestMapping(“/path”) :修饰类
,该控制器的请求路径
@Autowired : 修饰属性
,按照类型进行依赖注入
@PathVariable : 修饰参数
,将路径值映射到参数上
@ResponseBody :修饰方法
,该方法会返回Json数据
@RequestBody(需要使用Post提交方式) :修饰参数
,将Json数据封装到对应参数中
@Controller@Service@Compont: 将类注册到ioc
容器
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。