2019年java面试题总结——附有答案

能力有限望各位谅解,这些只是平常在学习的时候或者刷题的时候看到的,就随手记录了下来,不喜勿喷。配有答案,答案是自己总结的精简版,也许并不全面。要是把每道题的原理来一边太多了。此文章只针对面试过程中的临时发挥,用最精简的语言尽量涵盖全面!

1、java中能创建volatile数组吗?

答:能,只不过只是一个指向数组的引用,而不是整个数组,

如果改变了引用指向的数组,将会受到volatile的保护,但是如果多个线程同时改变数组的元素,volatile关键字就不能起到保护的作用。

2、volatile 能使得一个非原子操作变成原子操作吗?

答:能

3、volatile 修饰符的有过什么实践?

答:一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。

4、java中有哪些锁?以及他们的区别。

公平锁/非公平锁、可重入锁、独享锁/共享锁、互斥锁/读写锁、乐观锁/悲观锁、分段锁、偏向锁/轻量级锁/重量级锁、自旋锁

–公平锁:是指多个线程按照申请锁的顺序来获取锁。

–非公平锁:是指多个线程获取所得顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请锁的线程优先获取锁,有可能会造成优先级反转或者饥饿现象。

对比:一般开发用的默认是非公平锁,有点在于吞吐量比公平锁要大

–可重入锁:又名递归锁,是指在同一个线程的外层方法获取锁的时候,在进入内层方法会自动获取锁。

优点:对于Synchronized而言也是一个可重入锁。可重入锁的好处是可一定程度的避免死锁

–独享锁:是指该锁一次只能被一个线程所持有。

–共享锁:是指该锁可被多个线程持有。

Synchronized是独享锁

–哈希表的最差时间复杂度是 O(n^2),最快时间复杂度O(n)

5、String类可以被继承吗?为什么?

答:不可以,因为String类有final修饰符,而final修饰的类是不可以被继承的,实现细节不允许改变。

6、String,Stringbuffer,StringBuilder的区别?

答:String是java中的基础类,除了hash这个属性外其他属性都被声明为final,因为他是不可变的,拼接字符串是会产生很多无用的中间对象,所以频繁的拼接字符串

会对性能造成影响/ StringBuffer就是为了解决大量字符串拼接产生很多无用对象问题而提供的一个类,提供append和add方法,是可以把字符串添加到已有序列的

末尾或者指定位置,他本质是一个线程安全的不可修改的字符序列,把所有修改方法都加上了锁,但是性能不佳/ StingBuilder是JDK 1.5发布的 和StringBuffer

本质一样只是去掉了锁/底层都是利用可修改的char数组(JDk9以后都是byte数组了)

7、ArrayList和LinkedList有什么区别。

答:对于随机访问的get和set, ArrayList要优于LinkedList,因为LinkedList要移动指针。对于增加和删除操作add和remove,LinkedList比较占优势因为ArrayList要

移动数据。 ArrayList底层实现是数组而LinkedList底层实现是链表

8、hashmap和hashtable和concurrenthashmap区别和比较。

答:hashtable底层是数组+链表实现,key和value都不能为null,线程安全的,初始size为11,修改数据是会锁住整个hashtable效率比较低。

hashMap底层是数组+链表,key和value都可以是null,线程不安全,初始size为16,当Map中元素总数超过Entry数组的75%,触发扩容操作

扩容:newsize = oldsize*2 size一定为2的n次幂。

ConcurrentHashMap底层是数组+链表,是线程安全的,通过把Map分成N个段,可以提供相同的线程安全,但是效率提升16倍(读操作不加锁,因为hashEntry的value变量

是volatile的,也能保证读取到最新的值),ConcurrentHashMap允许多个修改并发进行,其关键是使用了锁分离技术。扩容:段内扩容,段内元素超过Entry数组长度

的75%触发扩容,不会对整个Map进行扩容,插入前检测是否需要扩容,避免无效扩容

— concurrenthashmap的锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;

而ConcurrentHashMap中则是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

9、JDK8中对HashMap做了怎样的优化。

1)在java8中如果链表长度超过8时,那么链表将会转换成红黑树,查询时间复杂度改变

因为红黑树的平均查找长度是log(n),长度为8的时候,平均查找长度为3。。如果继续使用链表,平均查找长度为8/2=4。

这才有转换为树的必要。。链表长度如果是6以内,6/2=3, 速度也很快的。转化为树还有生成树的时间,并不明智。

2)发生hash碰撞时,java1.7 会在链表头部插入,而1.8 会在链表尾部插入

3)在java 1.8中,Entry被Node替代(换了一个马甲)

10、有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。

答:TreeMap和LinkedHashMap是有序的(TreeMap是默认key升序的,LinkedHashMap是默认数据的插入顺序的)

TreeMap是基于比较器Comparator来实现有序的。

LinkedHashmap是基于链表来实现数据插入有序的。

10、描述动态代理的几种实现方式,分别说出相应的优缺点。

答:两种实现方式,一种是jdk的动态代理还有一种是cglib动态代理。

jdk动态代理是由java底层的反射原理实现的。而cglib是基于框架asm实现的动态代理,jdk方式生成类的过程中比较高效,而cglib是执行过程中效率比较高

(可以通过将asm生成的类加入缓存的方式来决绝生成类效率低的问题)

11、深拷贝和浅拷贝区别?

答:浅拷贝是对指针的拷贝,拷贝后两个指针指向同一个内存空间。深拷贝不但对指针进行拷贝,而且对指针所指向的内存空间的内容也进行了拷贝,经过深拷贝

后的指针是指向两个不同的地址指针

12、hashCode和equals方法的理解?

两个方法都是用来比较对象是否相等的,但是重写的equals()里一般比较全面比较复杂,所以效率比较低,但是hashCode只是比较hash值是否相等,效率比较高,

但是准确性比较差,有的时候不同的对象生成的hash值有可能相同

13、IO和NIO的区别

IO是面向流,是阻塞的。单线程一次只能应付一个连接。

NIO面向缓存,非阻塞,拥有选择器。可以单线程管理多个连接

====================JVM类====================

1、什么情况下会发生栈内存溢出?

答:如果线程请求分配的栈容量超过java虚拟机栈允许的最大容量的时候,java虚拟机将抛出一个StackOverFlowError异常

2、你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。

答:Serial收集器、Parallel(并行)收集器、CMS收集器(基于“标记-清除”算法实现的)、G1收集器(基于“标记-整理”算法实现的)

3、双亲委派模型

答:双亲委派模型工作过程是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。

每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。

防止黑客恶意篡改某些java类,进行注入恶意代码。

4、如何打破双亲委派机制

答:1、自己写一个类加载器2、重写loadclass方法3、重写findclass方法

5、怎么打出线程栈信息?

答:一、通过命令pidof java找到已经启动的java进程ID。二、使用命令kull-3 <java进行的pid> 打印出java程序的线程堆栈信息

6、简单讲讲tomcat结构,以及其类加载器流程,线程模型等

答:Tomcat启动时,会创建以下四个类加载器

一、Bootstrap引导类加载器:(主要加载JVM启动所需要的类)。

二、System系统类加载器:(主要加载Tomcat启动时的类)

三、Common通用类加载器(主要加载tomcat使用以及应用通用的一些类)

四、webapp应用类加载器(主要加载每个应用的class文件)

7、tomcat如何调优,涉及哪些参数

• -server:启用jdk的server版本。

• -Xms:虚拟机初始化时的最小堆内存。

• -Xmx:虚拟机可使用的最大堆内存。 #-Xms与-Xmx设成一样的值,避免JVM因为频繁的GC导致性能大起大落

• -XX:PermSize:设置非堆内存初始值,默认是物理内存的1/64。

• -XX:MaxNewSize:新生代占整个堆内存的最大值。

• -XX:MaxPermSize:Perm(俗称方法区)占整个堆内存的最大值,也称内存最大永久保留区域。

8、调用system.gc()马上就执行gc吗?

并不会马上执行gc,甚至不一定会执行gc。这句话只是建议jvm进行gc,当我们代码这样写的话会把gc请求记录下来

等到变量runFinalization=true的时候才会去执行gc。如果真需要马上gc代码应该是

System.gc();

runtime.runFinalizationSync();

System.gc();

不过虚拟机有自己的gc策略,不建议手动gc

===========================多线程==============

1、多线程的几种实现方式。

三种:继承Thread类、实现Runnable接口、实现Callable接口

2、volatile的原理,作用,能代替锁么。

volatile是轻量级同步机制。在访问volatile变量时不会执行加锁操作,因此也不会使线程阻塞,是一种比synchrinized关键字更轻量级的同步机制。

volatile无法同时保证可见性和原子性。加锁机制既可以保证可见性又可以保证原子性,而volatile只能保证可见性

3、sleep和wait的区别

一、sleep()方法属于Thread类,而wait()属于object类的方法

二、sleep方法会让程序暂停指定的时间,让出cpu,但是不会释放对象锁,而wait()方法线程会放弃对象锁,进入等待锁定池,当调用notify方法后获取对象锁进入运行状态。

4、sleep和sleep(0)的区别。

sleep(0)是为了让线程短暂让出cpu,sleep(0)释放当前线程所剩余的时间片(如果有剩余的话),这样可以让操作系统切换其他线程来执行,提升效率。

5、乐观锁,悲观锁。

悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。

乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。

6、Lock与Synchronized的区别

一、Lock是一个接口而synchronized是java中的关键字

二、synchronized在发生异常时会释放线程占有的锁,而lock在发生异常时不会释放锁,所以必须要在finally块中通过unLock()释放锁

三、在性能上lock在线程竞争激励的情况下lock的性能远大于sychronized

7、线程池的创建

创建线程池的类ThreadpoolExecutor

====================TCP与HTTP================

1、http状态码

http状态返回代码:1xx(临时响应)、2xx (成功)、3xx (重定向)、4xx(请求错误)、5xx(服务器错误)

一些常见的http状态返回代码为:

200 – 服务器成功返回网页

404 – 请求的网页不存在

503 – 服务不可用

2、如何避免浏览器缓存

每次请求后台加一个随机参数

3、如何理解HTTP协议是无状态的

http协议时无状态的,指的是协议对事物没有记忆能力,服务器不知道客户端是什么状态,http是同一个无状态面向连接的协议

4、什么是http长连接和短连接

(HTTP 1.0 默认)短连接:客户端和服务器每进行一次操作都会建立一次连接,结束就会关闭

(HTTP 1.1 默认)长连接:客户端和服务器进行一次操作后不会关闭连接,如果客户端再次访问这个网页,会继续之前的连接。

(会在响应头加入Connection:keep-alive),长连接有一定是保持时间在服务器软件中能设置这个时间

各自的优缺点:长连接可以省去较多的tcp连接和关闭操作,较少浪费,节省时间。 但是容易受到恶意攻击,所以设置过期时间

短连接对于服务器的管理较为简单存在的连接都是有用的。 但是如果客户端用户操作频繁,在tcp的建立和关闭上浪费时间和带宽

5、ping命令基于哪一层协议的原理是什么?

ping命令基于网络层的命令,是基于ICMP协议工作的。

6、分布式集群下如何做到唯一序列号

一、UUID,全局唯一

二、数据库递增

三、redis 单线程特性,递增

7、如何使用redis和zookeeper实现分布式锁?

redis实现分布式锁有两种方式 :

1) redis的方法setnx(key,value)如果key值不存在则设置当前key值为value,如果key值存在则直接返回。 expire()设置过期时间

2) 使用redis的getset()来实现分布式锁,此方法使redisTemplate.boundValueOps(key).getAndSet(value)的方法,

如果返回空,表示获取了分布式锁;如果返回不为空,表示分布式锁已经被其他程序占用

zookeeper实现分布式锁的两种方式:

1) zookeeper创建node节点,如果创建成功表示获取分布式锁,如果创建失败表示此锁已经被占用(多个线程创建一个节点node只有一个能创建成功)。

8、分布式事务的原理

CAP理论: C一致性 A可用性 P分区容错性 可用性和分区一直性是必要的两个条件,所以只能牺牲一致性

两阶段提交协议2PC 和三阶提交协议3PC

9、什么是hash一致性

在redis缓存集群的情况下,我们存储数据遵循数据库分库分表的原则,把大量数据分配到不同的缓存节点上,但是我们查找数据肯定不能遍历所有节点,

这样做是相当消耗性能的,所以我们用hash算法的方式,把一些数据分配到哪个redis节点区分出来。我们用hash值取模服务器个数的形式来得到应该存到哪个节点上,

取的时候也不会遍历所有服务器了,大大提高了性能。这虽然解决了性能问题,但是我们在增加服务器和某个服务器宕机的情况下所有的缓存位置都会变化,导致所有

缓存在一定时间会失效,从而造成缓存雪崩问题,这样一致性hash诞生。

一致性Hash算法是对2^32取模,假设整个存储空间是一个圆环的话,如果是四台服务器分别取模在圆环上四个节点。到时候数据分配的话取模后按顺时针遇到的第一个

服务器就存在这个里面,无论是服务器的增加或者减少只是影响其中一下段存储的位置发生改变,并不影响其他存储位置,具有良好的容错性和可扩展性

hash环的数据倾斜问题用虚拟节点的方法解决

10、kafka和其他消息队列的区别?

kafka的高性能,它的性能大大超过传统的MQ实现尤其是它还支持batch操作。

容错 每个partition的数据都会复制到几台服务器上

缺点:

重复消息、复杂性。kafka需要zookeeper集群的支持,topic通常需要人工来创建,部署和维护消息队列成本比较高

===================缓存=======================

1、如何防止缓存击穿和雪崩

缓存穿透:是值数据库和缓存中都没有的数据,而用户不断发起这样的请求。这是请求越过缓存对数据库攻击,导致数据库压力过大。

解决:接口层次增加数据校验,一些非法数据直接拦截。

如果在缓存中没有取到数据,数据库中也没有取到数据这是在缓存中设置这个key值为null。这样可以防止用户反复使用一个id进行暴力攻击

缓存击穿:缓存中没有数据但是数据库中有数据,由于缓存过期时间没有到,没有更新到数据库的最新数据,而这是用户大量访问这些数据,造成数据库压力增大

解决:对热点数据进行永久不过期设置

对数据库访问加上互斥锁

缓存雪崩:缓存雪崩是值一大批数据在缓存中同一时间过期,而查询数据量巨大,从而引起数据库压力过大

解决:设置热点数据永不过期

缓存数据过期时间设置随机,不要在同一时间过期

2、Redis的数据结构都有哪些?

五种数据类型:String(字符串)、list(链表)、set(无序不重复集合)、hash(键值对集合)、zset(有序集合)

3、redis有几种持久化方式?

RDB和AOF

RDB的优点:一旦采用这种方式redis数据库将只包含一个文件,这对于文件备份和恢复而言非常完美

AOF优点:数据的安全性及数据的持久性。AOF包含一个格式清晰易于理解的日志文件,记录了所有的修改操作

=====================事务=====================

1、@transactional注解在什么情况下会失效,为什么?

检查方法是不是public

异常类型是不是unchecked异常

数据库引擎是否支持事务

Spring是否扫描到你事务的这个包的注解了

是不是同一个类中调用的方法

异常是不是被catch住了

=====================数据库==================

1、MySQL的复制原理以及流程

基本原理流程,3个线程以及之间的关联;

主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中;

从:io线程——在使用start slave 之后,负责从master上拉取 binlog 内容,放进 自己的relay log中;

从:sql执行线程——执行relay log中的语句;

2、MySQL中myisam与innodb的区别,至少5点

(1)、问5点不同

1>.InnoDB支持事物,而MyISAM不支持事物

2>.InnoDB支持行级锁,而MyISAM支持表级锁

3>.InnoDB支持MVCC, 而MyISAM不支持

4>.InnoDB支持外键,而MyISAM不支持

5>.InnoDB不支持全文索引,而MyISAM支持。

3、InnoDb和MyISAM哪个select count(*)更快

答:MyISAM 因为它内部维护了一个计数器,可以直接调用

4、InnoDB有多少中日志?

答:六种

分别是:错误日志:记录错误信息、查询日志:记录所有对数据库请求的信息、慢查询日志:数据库设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中、

二进制日志:针对数据库改变的所有操作、中继日志、事物日志

5、InnoDB的行级锁是怎样加的?

答:语句后面加 for uodate

6、什么是视图?以及视图的使用场景有哪些?

答:视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。

对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

7、简单说一说drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

1、delete和truncate只删除表的数据不删除表的结构

2、速度,一般来说: drop> truncate >delete

3、delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;

4、如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.

8、mysql 的默认隔离级别?

MySQL的默认隔离级别是可重复读

9、如何查看sql的执行计划

orcale 客户端查询F5就行 也可以用关键字explain+sql语句

10、数据库会死锁吗,举一个死锁的例子,mysql怎么解决死锁

会产生死锁的情况,数据库锁一共有两种一个是排它锁一个是共享锁

当数据对象被加上排它锁时,其他事务是不能读取和修改的。加上共享锁其他事务是能够读取的但是不能修改。

数据库死锁的情况大部分是由于代码写得不够好造成的,提高代码质量时根本原因。举个例子用户A访问了A表(锁住了A表)然后又访问B表;

另一个用户访问了B表(锁住了B表)然后又去访问A表,这样就产生了死锁;这种情况一般是由程序的bug产生的。

11、MYsql的索引原理,索引的类型有哪些,如何创建合理的索引,索引如何优化。

索引的种类有:

普通索引:index(仅加速查询)。

唯一索引hash(加速查询+列值唯一可以有null)

主键索引 (加速查询+列值唯一不可以有null+表中只有一个)

全文索引 对文本的内容进行分词,进行搜索 (只有MYISAM引擎支持)

组合索引

12、mysql中in和exists()区别?

SELECT * FROM A WHERE id IN (SELECT id FROM B);

exists()适合B表比A表数据大的情况

当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用

    原文作者:奔跑的蜗牛
    原文地址: https://zhuanlan.zhihu.com/p/70781316
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞