1、ArrayList、Vector、LinkedList之间的区别?
ArrayList:底层数组,查询快,增删慢,线程不安全,效率高
Vector:底层数组,查询快(由于线程安全,其实查询也不快),增删慢,线程安全,效率低
LinkedList:底层双重链表,查询慢,增删快,线程不安全,效率高。
2、HashMap和Hashtable有什么区别?
HashMap允许null键null值,线程不安全,效率高
Hashtable不允许null键null值,线程安全,效率低
3、列举Collections工具类常用方法?
Collections.sort(list);按自然顺序排序;
Collections.binarySearch(list,key); 二分查找;
Collections.reverse(list) 反转;
Collections.shuffle(list) 随机替换;
4、final、finally、finalize的区别?
final:修饰类,不能被继承,修饰方法不能被重写,修饰变量是常量
finally:是异常处理的一部分,用于释放资源,一般来说代码肯定会执行,除非在执行finally之前,jvm退出了。
finalize:是Object的一个方法,用于垃圾回收。
5、如果catch里有return语句,请问finally还会执行吗?如果会是在return前还是return后?
会,在return前执行。不过finally的逻辑不会改变return的返回值。
6、实现多线程有几种方式?分别是什么
有三种方式,继承Thread类,实现runnable接口,实现callable接口
7、runnable与callable的区别?
Callable任务执行后可以有返回值,而runnable不能返回值,call方法可以抛出异常,而run方法只能try catch,运行callable任务可以拿到一个Future对象,callable依赖线程池。
8、使用线程池的好处?
使用线程池提高系统的性能,减少创建,销毁线程的资源开销,因为代码结束后,线程不会死亡,而是再回到线城池,等待下一个对象的调用。
9、线程的生命周期?
10、sleep()和wait()的区别?
Sleep会把执行机会给其他线程,到时后自动恢复,不会释放对象锁,wait会释放对象锁,只有对象发出notify或notifyAll才准备获取对象锁。
11、run()和start()的区别?
Run仅仅是调线程执行的普通方法,start首先会启动线程,由Jvm调用run方法。
12、写一个单例设计模式例子?
懒汉式
public class student{
private student(){}
private static student s=null;
public synchronized student getStudent(){
if(s==null){
s=new Student();
}
return s;
}
}
饿汉式
public class student{
private student(){}
private static student s= new Student();
public static student getStudent(){
return s;
}
}
13、spring是如何管理事务的?
Spring并不是直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给持久化机制所提供的相关平台框架的事务来实现,spring为不同的事务API提供一致的编程模型。
Spring的事务分为编程式事务和声明式事务,编程式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于将用户操作与事务规则进行解耦。
Spring提供两种方式的编程式事务管理,分别是使用transactionTemplate(线程安全的)和platformTransactionManager。
14、数据库事务的隔离级别?
由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable
15、spring事务的传播行为?
PROPAGATION_REQUIRED--支持当前事务,假设当前没有事务。就新建一个事务。
这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,假设当前没有事务,就以非事务方式运行。
PROPAGATION_MANDATORY--支持当前事务,假设当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,假设当前存在事务。把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式运行操作。假设当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式运行,假设当前存在事务,则抛出异常。
16、什么是AOP,AOP的作用是什么?
AOP,面向切面编程,就是把可重用的功能提取出来,然后将这些通用功能在合适的时候织入到应用程序中,比如事务管理、权限控制、日志记录、性能统计等。
AOP的作用
AOP并没有帮助我们解决任何新的问题,它只是提供了一种更好的办法,能够用更少的工作量来解决现有的一些问题,使得系统更加健壮,可维护性更好。
17、说一下spring的bean的生命周期?
1)Spring通常通过配置文件定义Bean
2)初始化Bean。 通过方法或则通过接口
3)Bean的调用 。通过BeanFactoy 或则 ApplicationContext
4)Bean的销毁 。通过方法或则接口来实现
18、过滤器、拦截器、AOP的区别?
过滤器作用于最外层,根据url配置进行过滤能拿到request,response,不能拿到处理的controller的类和方法信息,拦截器可以拿到类和方法信息,拿不到方法的参数,AOP可以拿到类,方法以及方法里的参数
19、redis的持久化?
有两种方式,RDB和AOF
RDB:当主机在上一次快照之后,下一次快照之前挂了,则在上一次快照的数据将全部丢失
AOF:将发送服务端的每一条命令都记录下来
AOF重写:去除数据的中间执行过程,保留最终数据命令。
20、简述redis的主从复制(读写分离)
当从库与主库建立主从关系后,从库会向主库发送SYNC命令。
主库接受到SYNC命令开始保存快照(RDB持久化)并将期间收到的写的命令缓存起来
快照完成后,主库会将快照文件和缓存写命令发送给从库
从库接收到后会载入快照文件并执行写的命令
之后主库每当接收到写的命令就会发送给从库,从而保证数据一致
21、redis的主从复制出现宕机怎么办?
如果从库宕机,重启后自动加入主从架构,增量更新
如果主库宕机,从库执行SLAVEOF NO ONE 断开主从关系,变成主库,主库重启后执行SLAVEOF 将其变为从库(RDB持久化)
22、redis哨兵的作用?
监控主从是否正常,主库故障自动将从库变为主库
23、简述下springsecurity的原理?
Springsecurity就是在访问我们自己的web资源前加了一系列的过滤器组成过滤器链,springsecurity两大核心认证和授权。而这些过滤器也不是直接处理用户的认证和授权,而是交给了认证管理器和决策管理器,认证管理器会把任务交给对应的provider,一般表单登录会选择DaoAuthenticationProvider,这个provider会交给UserDetailService去处理。所以我们实际项目中会实现这个UserDetailService接口,而不管我们自己设计的数据库如何,我们只需要在这个类里处理我们自己的逻辑。授权是通过权限表达式控制的。
24、项目中为什么要用springsecurity作为安全框架,而不是自己写个过滤器?
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,和AOP功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
25、简述下redis分布式锁?
Redis有两个命令setNs和getSet,我们用setNs的特性去加锁,为了避免出现死锁set的值设为当前时间加上过期时间,如果锁过期了,为了避免多个线程同时获得锁,在判断锁过期之后加getSet命令,判断getSet获得的值与原值是否相等,相等才能获取到锁。
26、简述下zookeeper的分布式锁?
Zookeeper有四种节点类型,持久节点,持久顺序节点,临时节点,临时顺序节点。Zookeeper会先创建一个持久节点,在此节点下面创建临时顺序节点,规定节点号最小的获取到锁,每个节点首先会判断自己是不是最小的节点,如果不是会监听他上一个节点,如果上一个节点挂了,此节点会再一次判断自己是不是最小的节点,是则获取到锁。临时顺序节点有效避免了羊群效应,而且拿到锁的节点挂掉不会导致其他节点无法获取到锁,有效避免了死锁问题。
27、抽象类和接口的区别?
抽象类的变量可以是各种类型的,而接口不能。
抽象类可以有非抽象的方法,而接口默认都是public abstract
抽象类只能单继承,而接口可以多实现
28、volatile和synchronized的区别?
1)volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2)volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3)volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4)volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5)volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
29、简述垃圾回收机制?
对象如果没有更多的指向则变成垃圾;gc()垃圾回收器,由虚拟机自动进行回收,gc回收规则是GC Roots引用链,GC首先从栈顶往下找引用的对象,然后到方法区中找引用的对象,当一个对象跟引用链没有连接则被回收,当调用System.gc()进行垃圾回收,内存回收对象前会调用对象的finalize()方法,如果对象不想被回收则需要重新再将引用指向对象即可。
30、谈谈你对jvm内存的理解?
jvm把管理的内存划分5个内存空间:方法区,堆,栈,本地方法栈,程序计数器。其中栈,本地方法栈,程序计数器是线程私有的,而堆,方法区是线程共享的,每个线程在堆中会预先分配一个内存块,方法区存储已被虚拟机加载的类的信息,常量,静态变量。
jvm区域总体分两类,堆区和非堆区,其中堆区又分为Eden space、survivor space、Tenured Gen(老年代)、Perm Gen(永久代)
对象在Eden Space创建,当Eden Space满了的时候,gc就把所有在Eden Space中的对象扫描一次,把所有有效的对象复制到第一个Survivor Space,同时把无效的对象所占用的空间释放。当Eden Space再次变满了的时候,就启动移动程序把Eden Space中有效的对象复制到第二个Survivor Space,同时,也将第一个Survivor Space中的有效对象复制到第二个Survivor Space。如果填充到第二个Survivor Space中的有效对象被第一个Survivor Space或Eden Space中的对象引用,那么这些对象就是长期存在的,此时这些对象将被复制到Permanent Generation。
若垃圾收集器依据这种小幅度的调整收集不能腾出足够的空间,就会运行Full GC,此时jvm gc停止所有在堆中运行的线程并执行清除动作。
31、简述类加载过程和类加载机制
类加载器种类有上到下分根类加载器,扩展类加载器,系统类加载器,自定义加载器。
类加载的阶段:
加载:将类的class文件读入内存,并创建一个java.lang.Class对象放入方法区
验证:检测被加载的类是否有正确的内部结构,会不会威胁虚拟机的安全等
准备:为static修饰的变量分配内存,并设置初始值,int型的是0,如果是static final修饰的,则进入常量池
解析:将类的二进制数据中的符号引用替换为直接引用。
初始化:当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先触发其父类的初始化,将准备阶段的初始值完成赋值。初始化运行主类,比如main方法。
32、如何实现分布式事务?
1)可以采用消息事务+最终一致性:将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作,其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了,这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功,这样就变相地实现了A与B的分布式事务。
2)TCC编程模式:TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作。以在线下单为例,Try阶段会去扣库存,Confirm阶段则是去更新订单状态,如果更新订单失败,则进入Cancel阶段,会去恢复库存。总之,TCC就是通过代码人为实现了两阶段提交,不同的业务场景所写的代码都不一样,复杂度也不一样,因此,这种模式并不能很好地被复用。
33、cookie和session的区别?
1)cookie数据存放在客户的浏览器上,session数据放在服务器上。
2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑安全应该使用session。
3)session会在一定时间内保存在服务器上,当访问增多,会比较占用服务器的性能。
4)单个cookie保存的数据不能超过4K
34、写一个死锁的例子
public class TestThread {
public static void main(String[] args) {
// test dead lock
Thread t9 = new Thread(
new DeadLock(true));
Thread t10 = new Thread(
new DeadLock(false));
t9.start();
t10.start();
}
}
class DeadLock implements Runnable{
boolean lockFormer;
static Object o1 = new Object();
static Object o2 = new Object();
DeadLock(boolean lockFormer){
this.lockFormer = lockFormer;
}
@Override
public void run() {
if(this.lockFormer){
synchronized (o1) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("1ok");
}
}
}else{
synchronized (o2) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("1ok");
}
}
}
}
}
35、ThreadLocal 与 Synchronized区别?
相同:ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。
不同:Synchronized同步机制采用了“以时间换空间”的方式,仅提供一份变量,让不同的线程排队访问;而ThreadLocal采用了“以空间换时间”的方式,每一个线程都提供了一份变量,因此可以同时访问而互不影响。
36、堆内存中的新生代,分为Eden区和两个survivor区,请问为什么需要2个survivor?
假如不分为两个survivor,一旦Eden满了,触发一次Minor GC,那么eden中有引用的对象就会移到survivor区,那么下一次Eden满了,再一次Minor GC,survivor和Eden各有一部分存活对象,此时再把Eden的存活对象放到Survivor中,会导致内存的碎片化,碎片化严重影响java性能,导致堆中没有足够大的连续内存空间。
37、谈谈你对spring IOC的理解?
在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转Ioc是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
38、HTTP 2.0与HTTP 1.1区别
HTTP/2采用二进制格式而非文本格式
HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
使用报头压缩,HTTP/2降低了开销
HTTP/2让服务器可以将响应主动“推送”到客户端缓存中
39、数据库连接池的原理?
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定 连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量使用情况,为系统开发,测试及性能调整提供依据
1).空闲连接池(存放已经创建但并未分配出去的连接,按照创建时间大小放在一个容器)
2).用户请求连接时会看连接池内是否还有空闲连接..分配一个最大创建时间的连接给它
3).如果有空闲连接.判断该连接是否有效,如果是无效的连接,则把它移出连接池,重新检测是否还有其他空闲的连接
4).如果没有剩余空闲的连接,检查当前所开的连接池数是否达到连接池所允许的最大数,如果没有达到就分配一个新的连接,如果达到了就等待一段时间。
5).在等待的时间内,任何连接被释放出来后都可以把这个连接分配给等待的客户
6).如果等待时间超过预定的时间则返回null值,系统对已经分配出去了的正在使用的连接只做计数。
40、http与https的区别?
在URL前加https://前缀表明是用SSL加密的。 你的电脑与服务器之间收发的信息传输将更加安全。
Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的,...
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议
要比http协议安全。
41、简述CocurrentHashMap?
CocurrentHashMap利用锁分段技术增加了锁的数目,从而使争夺同一把锁的线程的数目得到控制。
锁分段技术就是对数据集进行分段,每段竞争一把锁,不同数据段的数据不存在锁竞争,从而有效提高 高并发访问效率。
CocurrentHashMap在get方法是无需加锁的,因为用到的共享变量都采用volatile关键字修饰,保证共享变量在线程之间的可见性(每次读取都先同步缓存和内存,直接从内存中获取值,虽然不是原子操作,但根据JAVA内存模型的happen before原则,对volatile字段的写入操作先于读操作,能够保证不会脏读),volatile为了让变量提供线程之间的内存可见性,会禁止程序执行结果的重排序(导致缓存优化的效果降低)
42、redis可以存储哪些数据类型?
redis常用五种数据类型:string,hash,list,set,zset(sorted set).
43、mysql索引失效的几种情况?
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
2.对于多列索引,不是使用的第一部分,则不会使用索引
3.like查询是以%开头
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
44、mysql的执行计划explain列的解释?
运行上面的sql语句后你会看到,下面的表头信息:
table | type | possible_keys | key | key_len | ref | rows | Extra
EXPLAIN列的解释
table
显示这一行的数据是关于哪张表的
type
这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
说明:不同连接类型的解释(按照效率高低的顺序排序)
system:表只有一行:system表。这是const连接类型的特殊情况。
const :表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待。
eq_ref:在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用。
ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好。
range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况。
index:这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)。
ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免。
possible_keys
显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key
实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len
使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数
rows
MYSQL认为必须检查的用来返回请求数据的行数
Extra
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢