面试
个别都是由浅到深去问,思路是:
- 先考查根底是否过关,因为基础知识决定了一个技术人员倒退的下限
- 再通过深度考查是否有技术激情和深度以及技术的广度
同时可能会提出一些质疑和挑战来考查候选人是否与有不同意见的人沟通
考查内容和形式
基础知识
- 技术上深度与广度兼顾
基础知识: 考查根底的时候个别都不会深刻地去问,次要目标是考查知识面
计算机实践根底:
- 计算机网络
- 数据结构
- 计算机组成原理
- 计算机操作系统
JDK:
- 源码
- 汇合
- BIO或者NIO
- annotation等
JVM:
- 内存模型
- 类加载原理
数据库:
- 索引
- 事务
- 死锁等
并发:
- 并发的优缺点
- 内存可见性 - volatile
- 锁
- 同步
- 线程池框架
网络:
- TCP
- HTTP
常见设计模式
深刻考查
深刻考查:
- 深刻考查不会像考查根底时八面玲珑,而是会在某个点上深刻去聊
- 这个点能够是让候选人本人选一个点,也可能面试官依据简历内容去选
- 次要目标是考查候选人对某个技术点的深刻把握水平
- 技术是相通的,如果一个人能在某个技术点上达到很深刻的水平,其余点上也不会有太大问题,如果某个人在宣称很理解的技术点上都支支吾吾,只知其一;不知其二,多半能够判断此人要么技术无限,要么遇到问题不愿深刻考查
- 考查工程师的工程能力,比方: 做过哪些项目? 遇到最难的问题是什么? 怎么解决的? 说说最有成就感的一项工作
深刻考查的技术点:
Java框架:
- Spring源码的AOP和IOC
JDK:
- ConcurrentHashMap如何进步并发度
- NIO的原理,包含零拷贝,堆外内存以及优缺点
虚拟机:
- 包抵触,类抵触的造成原理以及解方法,能够引申到JDK 9的模块化设计
- TCCL的存在价值
服务器:
- Tomcat源码
- Netty源码
数据结构:
- 数组
- 链表
- 树
- 图
- 排序
- 算法
分布式:
- 缓存利用
- 一致性哈希
- RPC原理和设计 - 通信协议,序列化形式,超时机制等
- 负载平衡
- 分布式缓存架构设计
- 分布式音讯
- 音讯队列设计与应用
- 分布式环境下中间件部署
- 分布式事务
- paxos
中间件:
- MQ
- ES
数据库:
- 数据库性能优化 - 慢SQL,索引优化,大事务,内核参数调优
- MySQL数据库底层原理
- 工作中遇到的数据库问题以及解决办法
- Redis
并发:
- 非阻塞锁CAS
- 并发对编译器优化的影响
- 线程池调优
- 工作中遇到的并发问题以及解决办法
技术趋势:
- Docker
微服务
业务相干
- 做的我的项目所应用的技术栈以及其中的优缺点?
- 如果从零开始,能不能从新将其实现?
- 以后零碎的应用方是谁? 用户量多大? 用户集中应用的工夫点?
- 零碎落下了哪些数据? 这些数据的应用方是谁? 零碎的依赖方是谁?
从技术,产品,业务的角度去画下相干的流程图
工作交接
和产品,业务,经营,技术之间的工作交接:
- 晓得本人的职责边界
- 弄清楚哪些是本人须要做的
- 哪些是其余的人应该做的
交换起来不卑不亢
面试筹备
面试最好的筹备形式:
- 肯定是平时多多积攒
- 遇到问题不要回避
- 深刻去思考并解决
- 在解决一个个问题的过程中积攒解决问题的能力,造成本人的常识体系
如何提前准备将本人平时积攒展示进去:
- 针对面试考查内容知识点思考答案以及扩大.如果能晓得大部分,就要更加深刻一部分.这个过程次要是整顿本人的常识体系
- 回顾整顿简历和过往我的项目中的"难点","亮点",因为这是用来辨别候选人的重要的点.面试肯定会问"在我的项目中经验最大的技术难点是什么?" 整顿一下思路,不至于在面试时因为工夫长远而回顾不起来细节影响面试成果
沟通过程要做到有理有据,不卑不亢.在技术问题上保持本人的主观和准则,依据独特认可的事实进行逻辑判断得出观点
面试内容
Java根底
private润饰的办法能够通过反射拜访,那么private意义是什么?
考查对Java设计的把握水平
- Java的private修饰符并不是为了相对安全性设计的,更多的是对用户惯例应用Java的一种束缚
- 从内部对对象进行惯例调用时,能够清晰理解类构造
- Java中如何利用反射获取一个类的字段?
- 常见的类加载
Java类的初始化程序?
Java类的初始化程序:
- 基类动态代码块,基类动态成员变量(并列优先级,依照代码中呈现的先后顺序执行,并且只有第一次加载时执行)
- 派生类动态代码块,派生类动态成员变量(并列优先级,依照代码中呈现的先后顺序,并且只有第一次加载时执行)
- 基类一般代码块,基类一般成员变量(并列优先级,依照代码中呈现的先后顺序执行)
- 基类构造函数
- 派生类一般代码块,派生类一般成员变量(并列优先级,依照代码中呈现的先后顺序执行)
- 派生类构造函数
局部变量应用前须要显式赋值,否则编译通过不了,为什么须要这么设计?
成员变量:
- 能够不经初始化,在类的加载过程中的筹备阶段能够赋予默认值
- 赋值和取值拜访的先后顺序具备不确定性
- 成员变量能够在一个办法调用前赋值,也能够在办法调用后进行赋值. 这是在运行时产生的,编译器确定不了,所有交给JVM来赋值
局部变量:
- 在应用之前须要显式赋予初始值
- 局部变量的赋值和拜访程序是确定的
这样设计是一种束缚,尽最大可能缩小使用者犯错:
- 倘若局部变量能够应用默认值,可能总会无意间遗记赋值,进而导致不可预期的状况产生
- ArrayList,LinkList的区别?插入和查找哪个更快?
- ArrayList的随机插入?
- LinkList是单向链表还是双向链表?
- 单向链表如何实现一个栈?
- HashMap的put操作底层是如何实现的?
- HashTable,ConcurrentHashMap的区别?为什么ConcurrentHashMap并发度更高?
- ConcurrentHashMap中的get和set什么时候会加锁?如果不加锁会产生什么问题?什么时候是CAS操作?
HashMap的原理,在Java 8中做了哪些扭转?
从构造实现上来讲:
- HashMap实现是数组+链表+红黑树(红黑树局部是JDK 1.8之后减少的)
- HashMap最多容许一条记录的键为null,容许多条记录的值为null
- HashMap是非线程平安的
String与StringBuilder的区别?
可变与不可变:
- String不可变,每一次执行 "+" 都会新生成一个新对象,所以频繁扭转字符串的状况下不必String,以节俭内存
是否多线程平安:
- StringBuilder并没有对办法进行加同步锁,所以是非线程平安的.StringBuffer和String都是线程平安的
Vector和Array的区别?
- ArrayList在内存不够时默认扩大是50%+1个,Vector默认是扩大1倍
- Vector是属于线程安全级别的,然而大多数状况下不应用Vector,因为线程平安须要更大的零碎开销
HashMap和HashTable的区别?
- HashTable继承Dictionary类,HashMap继承AbstrctMap类
- HashTable不容许空键值对,而HashMap容许空键值对,但最多只有一个空对象
- HashTable同步,而HashMap不同步,效率上比HashTable要高
ConcurrentHashMap和HashTable比拟,两个线程并发拜访Map中同一条链,一个线程在尾部删除,一个线程在后面遍历查找.为什么后面的线程还能正确的查找到前面被另一个线程删除的节点?
ConcurrentHashMap交融了HashTable和HashMap二者的劣势:
- HashTable是做了同步的,是线程平安的,而HashMap未思考同步,所以HashMap在单线程状况下效率比拟高
- HashTable在多线程的状况下,同步操作能保障程序执行的正确性
- 然而HashTable是阻塞的,每次同步执行的时候都要锁住整个构造
ConcurrentHashMap正好解决了效率和阻塞问题:
- ConcurrentHashMap容许多个批改操作并发进行,技术的要害是应用了锁拆散,即一个Array保留多个Object,应用这些对象的锁作为拆散锁,get或者put的时候随机应用任意一个
- ConcurrentHashMap应用了多个锁来管制对Hash表的不同局部进行的批改
从JDK 1.6开始,在HashEntry构造中,每次插入将新增加节点作为链的头节点,这与HashMap实现雷同.
- 每次删除一个节点时,会将删除节点之前的所有节点拷贝一份组成一个新的链,而将以后节点的上一个节点的next指向以后节点的下一个节点.从而在删除当前会有两条链存在
- 因而能够保障即便在同一条链中,有一个线程在删除,而另一个线程在遍历,都能工作良好.因为遍历的线程能持续应用原有的链
在Java 8中,应用volatile HashEntry保留数据,table元素作为锁.从Table数组+单向链表又加上了红黑树
红黑树是一种特地的二叉查找树,红黑树的个性:
- 节点为红或黑
- 根节点为黑
- 叶节点为黑
- 一节点为红,则一节点为黑
- 一节点到其子孙节点所有门路上的黑节点数目雷同
ArrayList和LinkedList的区别?
- ArrayList底层的数据结构是数组,反对随机拜访.LinkedList的底层数据结构是链表,不反对随机拜访
应用下表拜访一个元素:
- ArrayList的工夫复杂度是O(1)
- LinkedList的工夫复杂度是O(n). LinkedList是双向链表
- HashMap中put()元素产生抵触,为什么应用LinkedList拉链法解决而不必ArrayList解决?产生抵触时key值不等,新元素怎么样退出链表?为什么这么设计?
Java中的Comparator和Comparable有什么不同?
- Comparable接口用于定义对象的天然程序,是排序接口
Comparator通常用于定义用户定制的程序,是比拟接口
- 如果须要管制某个类的秩序,而该类自身不反对排序,即没有实现Comparable接口,就能够建设一个"该类的比拟器"来进行排序
- Comparable总是只有一个,然而能够有多个Comparator来定义对象的程序
抽象类是什么?与接口有什么区别?为什么要应用抽象类?
- 抽象类是不容许被实例化的类,一个类只能应用一次继承关系,然而一个类能够实现多个接口
抽象类和接口所反映出的设计理念不同:
- 抽象类示意的是 "is - a"
- 接口示意的是 "like - a"
实现抽象类和接口的类必须实现其中的所有办法.抽象类能够有非形象办法,接口中则不能有实现办法,然而在Java 8中容许接口中有动态默认办法
- 接口中定义的变量默认是public static final型,且必须给出初值,所以实现类中不能从新定义,也不能扭转这个值
- 抽象类中定义的变量默认是friendly型,这个变量的值能够在子类中从新定义,也能够从新赋值
- 子类中实现父类中的形象办法时.可见性能够大于等于父类中的
- 接口实现类类中的接口办法的可见性只能与接口中的雷同,即为public
- 应用抽象类是为了重用,缩小编码量,升高耦合性
Java中的重载和重写?
- 重载和重写都是应用雷同的名称实现不同的性能,然而重载是编译时流动,重写是运行时流动
- 能够在同一个类中重载办法,但只能在子类中重写办法,重写必须要有继承
重载:
- 重载的时候,办法名要一样,然而参数类型和参数个数不一样,返回值类型能够雷同也能够不同
- 无奈以返回型别作为重载函数的辨别规范
重写:
- 在子类中能够依据须要对从基类中继承的办法进行重写
- 重写的办法和被重写的办法必须具备雷同的办法名称,参数列表和返回类型
- 重写办法不能应用比被重写办法更严格的拜访权限
Collection和Collections的区别是什么?
- Collection< E >是Java汇合框架中的根本接口
- Collections是Java汇合框架提供的一个工具类,其中蕴含了大量用于操作和返回汇合的静态方法
Java中多态的实现原理?
- 多态指的是父类援用指向子类的对象,调用办法时会调用子类的实现而不是父类的实现
- 多态的实现关键在于动静绑定
Object中定义了哪些办法?
- clone()
- equals()
- hashCode()
- toString()
- notify()
- notifyAll()
- wait()
- finalize()
- getClass()
Java中的泛型和类型擦除?
- 泛型即参数化类型,在创立汇合时,指定汇合元素的类型,此汇合只能传入该类型的参数
类型擦除:Java编译器生成的字节码不包含泛型信息,所以在编译时擦除
- 泛型用最顶级的父类替换
- 移除
JDK 1.8引入的新个性?
- Lambda表达式
- 容许像对象一样传递匿名函数Stream API,充分利用古代多核CPU,能够写出很简洁的代码
- Date与Time API,有一个稳固简略的日期和工夫库可供使用
- 接口中能够有动态,默认办法
- 反复注解,能够将雷同的注解在同一类型上应用屡次
Java中public,private,protected以及默认关键字的拜访范畴?
- protected可在包内及包外子类拜访
- default只能在同一包内拜访
- private只能在同一个类中拜访
罕用的数据结构?
- 汇合
线性构造
- 数组
- 队列
- 链表
- 栈
- 树形构造
- 图状构造
Java中的TreeMap是采纳什么树实现的?
Java中的TreeMap是应用红黑树实现的
匿名外部类是什么?如何拜访在匿名外部类里面定义的变量?
- 匿名外部类就是没有名字的外部类,匿名外部类只能应用一次,通常用来简化代码编写
- 匿名外部类只能拜访外部类的final变量
- 在Java 8中,如果局部变量被匿名外部类拜访,那么该局部变量相当于主动应用了final润饰
如何高效地创立一个线程平安的单例模式?
- 通过枚举
- 通过动态外部类
- 也能够通过双重查看创立单例模式,然而这种单例模式是线程不平安的
poll()办法和remove()办法的区别?
- poll()和remove都是从队列中取出一个元素
- poll()在获取元素失败时会返回空
- remove()在获取元素失败时会抛出异样
写一段代码在遍历ArrayList时移除一个元素?
应用迭代器
Iterator it = list.iterator();while (it.hasNext()) { if (...) { it.remove(); }}
- 注解的原理
开源协定哪些?
- GPL: GNU General Public License,GNU通用公共许可协定
- LGPL: GNU Lesser General Public License, GNU宽通用公共许可协定
- BSD: Berkeley Software Distribution, 伯克利软件散发许可协定
- MIT: Massachusetts Institute of Technology
- Apache: Apache Licence, Apache许可协定
- MPL: Mozilla Public Licence, Mozilla公共许可协定
线程
线程同步与阻塞关系?同步肯定阻塞吗?阻塞肯定同步吗?
- 线程同步与否和阻塞非阻塞没有关系
- 同步是一个过程,阻塞是线程的一种状态
- 多个线程操作共享变量时会呈现竞争
- 须要应用同步来避免两个以上的线程同时进入临界区内,在这个过程中,后进入临界区的线程将阻塞,期待先进入的线程走出临界区
同步和异步有什么区别?
- 同步和异步最大的区别是: 一个须要期待,一个不须要期待
同步能够避免出现死锁,读脏数据的产生,个别共享某一资源的时候应用
- 如果每个人都有批改权限,同时批改一个文件,有可能使一个人读取另一个人曾经删除的内容,就会出错
- 同步就会依照程序来批改
线程池?
- 线程池的作用是依据零碎本身的状况,无效的限度执行线程的数量,使得运行成果达到最佳
线程池次要执行的是:
- 管制执行线程的数量
- 超出数量的线程排队等待
- 期待有工作执行结束
- 再从队列中最后面取出工作执行
如何调用wait()办法?应用if块还是循环?为什么?
wait()办法应该在循环中调用:
- 因为当线程获取到CPU开始执行的时候,其余条件可能还没有满足
- 所以在解决前,循环检测条件是否满足更好
- wait(),notify()和notifyAll()办法是java.lang.Object类为线程提供的用于实现线程间通信的同步控制的期待和唤醒办法
实现线程的几种办法?
实现线程的办法:
- 继承Thread类,重写run函数
- 实现Runnable接口,重写run函数
- 实现Callable接口,重写call函数
什么是多线程环境下的伪共享 - false sharing?
伪共享是多线程零碎(这个零碎的每隔处理器都有本人的部分缓存)中一个普遍存在的性能问题
- 缓存零碎中是以缓存行(cache line)为单位存储的
- 缓存行是2的整数幂个间断字节,个别为32 - 256字节
- 最常见的缓存行是64个字节
- 当多线程批改互相独立的变量时,如果这些变量共享同一个缓存行,就会影响彼此的性能,这就是伪共享
- 线程的状态?
concurrent包上面,都用过哪些包?
- java.util.concurrent
- java.util.concurrent.atomic
- java.util.concurrent.lock
ReadWriteLock读写之间互斥吗?
ReadWriteRock读写锁的应用场景:
- 读 - 读
- 读 - 写
- 写 - 写
- 除了读 - 读之间是共享的,其余都是互斥的
怎么实现互斥锁和同步锁
- 考查对AQS, CAS的把握水平
Java并发编程中的辅助类?
- Semaphore
- CountDownLatch
- CyclicBarrier
- Exchanger
- CountDownLatch和CyclicBarrier之间的区别?
ReadWriteLock之间互斥吗?
ReadWriteLock读写锁的应用场景:
- 读,读
- 读,写
- 写,写
- 除了读和读之间是共享的,其余都是互斥的
这样之后会探讨怎么实现互斥锁和同步锁的,理解对AQS,CAS的把握水平,技术学习深度
Semaphore拿到执行权的线程之间是否互斥?
- Semaphore拿到执行权的线程之间是互斥的
- Semaphore, CountDownLatch, CyclicBarrier, Exchanger是Java并发编程中的4个辅助类,理解CountDownLatch和CyclicBarrier之间的区别
- Semaphore可能有多把锁,能够容许多个线程同时领有执行权,这些有执行权的线程如果并发拜访同一对象,会产生线程平安问题
Semaphore:
- 能够有多把锁,容许多个线程同时领有执行权
- 这些有执行权的线程如果并发拜访同一对象,会产生线程平安问题
- 线程是怎么依照程序执行的?
- 线程执行过程中遇到异样会产生什么,怎么解决?
写出一个单例模式?
- 单例模式是最常遇到的设计模式之一,考查对常常碰到的问题的了解的深度
单例一共有5种实现形式:
- 饿汉
- 懒汉
- 动态外部类
- 双检锁
- 枚举
要是写了简略的懒汉式可能会问: 要是多线程状况下怎么保障线程平安呢?
- 应用双检锁能够保障线程平安.
为什么要两次校验?光是双检锁还会有什么问题?
- 对象在定义的时候加上volatile关键字
- 引申探讨原子性和可见性,Java内存模型,类的加载过程
枚举形式,动态外部类,双检锁都能够实现单例模式. 双检锁的单例模式:
public Class Singleton { private Singleton() {}private volatile static Singleton instance;public static Singleton getInstance() { if (null == instance) { synchronized (Singleton.class) { if (null == instance) { instance = new Singleton(); } } } return instance;}}
- 双检锁写一个单例模式,为什么要应用volatile润饰对象?
- Object object = new Object();这里的object为null吗?为什么?
- Object object = new Object();初始化的程序是什么?在JVM各个区域做了什么?
什么状况下会产生死锁?写一个死锁?
- 死锁的四个条件:
示例: 定义两个ArrayList,都加上锁A,B.线程1,2. 线程1获取到锁A,申请锁B. 线程2获取到锁B,申请锁A. 在期待对方开释锁的过程中都不会让出已取得的锁
public class DeadLock { public static void main(String[] args) { final List<Integer> list1 = Arrays.asList(1, 2, 3); final List<Integer> list2 = Arrays.asList(4, 5 ,6); new Thread(new Runnable() { @Override public void run() { synchronized (list1) { for (Integer i : list1) { System.out.println(i); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (list2) { for (Integer i : list2) { System.out.println(i); } } } } }).start(); new Thread(new Runnable() { @Override public void run() { synchronized (list2) { for (Integer i : list2) { System.out.println(i); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (list1) { for (Integer i : list1) { System.out.println(i); } } } } }).start(); }}
String a = "ab"; String b = "a" + "b"; a == b; 是否相等,为什么?
- 相等
- new一个对象赋给变量
- 这行表达式创立了几个对象
int a = 1; 是原子性操作吗?
- 是
能够应用for循环间接删除ArrayList的特定元素吗?可能会呈现什么问题?怎么解决?
不能够应用for循环间接删除ArrayList中的特定元素:
- 不同的for循环会产生不同的异样
- 泛型for会抛出ConcurrentModificationException
- 一般的for想要删除汇合中反复且间断的元素,只能删除第一个
起因:
- JDK中的ArrayList源码
ArrayList中的remove有两个同名办法,只是入参不同:
入参为Object的实现:
- 个别状况下程序的执行门路走到else门路下最终调用faseRemove() 办法,会执行System.arraycopy() 办法,导致删除元素时波及到数组元素的挪动
- 一般for循环,在 遍历第一个合乎删除条件的字符串时将该元素从数组中删除,并且将后一个元素即第二个元素挪动到以后地位,导致下一次遍历时后一个字符串并没有遍历胜利,所以无奈删除. 这种能够应用倒序删除的形式来防止
解决办法: 应用迭代器Iterator
List<String> list = new ArrayList(Arrays.asList("a", "b", "b", "c", "d"));Iterator<String> iterator = list.iterator();while (iterator.hasNext()) { String element = iterator.next(); if ("b".equals(element)) { iterator.remove(); }}
新的工作提交到线程池,线程池是怎么解决的?
- 第一步: 线程池判断外围线程池里的线程是否都在执行工作. 如果不是,则创立一个新的工作线程来执行工作. 如果外围线程池里的线程都在执行工作,则执行第二步
- 第二步: 线程池判断工作队列是否曾经满了. 如果工作队列没有满,则将新提交的工作存储在这个工作队列中期待. 如果工作队列满了,则执行第三步
- 第三步: 线程池判断线程池的线程是否都处于工作状态. 如果没有,则创立一个新的工作线程来执行工作. 如果曾经满了,则交给饱和策略来解决这个工作
AQS和CAS原理?
形象队列同步器AQS: AbstractQueuedSychronizer
- 如果说java.util.concurrent的根底是CAS的话,那么AQS就是整个Java并发包的外围
- ReentrantLock, CountDownLatch, Semaphore都用到了AQS
AQS实际上以双向队列的模式连贯所有的Entry:
- ReentrantLock: 所有期待的线程都被放在一个Entry中并连成双向队列,后面一个线程应用ReentrantLock好了,则双向队列实际上的第一个Entry开始运行
- AQS定义了对双向队列所有的操作,并且只凋谢了tryLock和tryRelease办法给开发者应用.开发者能够依据本人的实现重写tryLock和tryRelease办法来实现本人的并发性能
比拟并替换CAS: Compare and Swap
假如有三个操作数:
- 内存之V
- 旧的预期值A
- 要批改的值B
- 当且仅当预期值A和内存值V雷同时,才会将内存值批改为B并返回true. 否则什么都不做并返回false.
- 整个比拟并替换的操作是一个原子操作
- CAS必须要volatile变量配合,这样能力保障每次拿到的变量是主内存中最新的响应值. 否则旧的预期值A对某条线程来说,永远是一个不会变的值A. 只有某次CAS操作失败,则CAS操作永远不会胜利
CAS高效地解决了原子操作的问题,但依然存在三大问题:
- 循环工夫长开销很大
- 只能保障一个共享变量的原子操作
- ABA问题
- AtomicLong的底层实现原理?
- ReentrantLock是可重入锁,什么是可重入锁?
- CAS底层是怎么样实现原子性的?
synchronized底层实现原理?
synchronized(this)原理:
- 两条指令: monitorenter和monitorexit
- 同步办法: 从同步办法的反编译的后果中能够看出 - 办法的同步并没有通过指令monitorenter和monitorexit来实现,绝对于一般办法,在常量池中多了ACC_SYNCHRONIZED标识符
JVM就是依据ACC_SYNCHRONIZED标识符来实现办法同步的:
- 当办法被调用时,调用指令将会查看办法的ACC_SYNCHRONIZED拜访标记是否被设置
- 如果设置了,执行线程将先获取monitor,获取胜利之后能力执行办法体,办法执行完之后再开释monitor
- 在办法执行期间,其余任何线程都无奈再取得同一个monitor对象
- lock和synchronized的区别?
- Java对象头信息,偏差锁,轻量锁,重量级锁及各自相互间的转化?
- 润饰类的锁和润饰办法的锁的区别?
volatile作用,指令重排相干?
- 了解volatile关键字的作用的前提是要了解Java的内存模型
volatile关键字的作用次要有两点:
- 多线程次要围绕可见性和原子性两个个性开展.应用volatile关键字润饰的变量,保障了在多线程之间的可见性.即每次读取到volatile变量,肯定是最新的数据
- 底层代码的执行: Java代码 -> 字节码 -> 依据字节码执行对应的C/C++代码 -> C/C++代码被编译成汇编语言 -> 和硬件电路交互.事实中,为了获取更好的性能,JVM可能会对指令进行重排序,多线程下可能会呈现意想不到的问题.应用volatile则会禁止对语义重排序,不过也会肯定水平上升高代码的执行效率
- 从实际角度而言,volatile的一个重要作用就是和CAS联合,保障了原子性. 比方AtomicInteger
Java线程池
- 线程池的工作原理以及外围参数
- 线程池的结构参数?
- 如何中断一个线程,具体实现?正在running的线程可能被中断吗?
- 线程中的线程个数,如何来设置?计算性的个数是CPU的个数还是CPU个数的2倍?
- CPU 100%怎么定位?
数据结构
B树和B+树是解决什么样的问题的?怎么演变过去的?两者之间的区别是什么?
- B树和B+树,既考查MySQL索引的实现原理,也考查数据结构根底
首先从二叉树说起:
- 因为会产生进化景象,提出均衡二叉树
- 再提出怎么样让每一层放的节点多一些来缩小遍历高度,引申出m叉树
- m叉搜寻树同样会有进化景象,引出m叉均衡树,即B树
- 这个时候每个节点既放了key又放了value.怎么使每个节点放尽可能多的key值,以缩小遍历高度也就是拜访磁盘的次数
- 能够将每个节点只放key值,将value值放在叶子节点,在叶子节点的value值减少指向相邻节点的指针,这就是优化后的B+树
而后谈谈数据库索引生效的状况:
- 为什么给离散度低的字段,比方性别建设索引是不可取的?查问数据反而更慢
- 如果将离散度高的字段和离散度低的字段,比方性别建设联结索引会怎么,有什么须要留神的?
Spring
- 看过哪些框架的源码?
- 什么是Spring框架? Spring框架有哪些模块?
- Spring中应用了哪些设计模式?
- Spring框架的益处?
- 什么是IOC管制反转?
- 什么是依赖注入以及原理?
- Spring中@Autowired和@Resource的区别?
- BeanFactory和ApplicationContext有什么区别?
- Spring Bean的生命周期?
- Spring Bean的作用域有哪些以及各种作用域之间有什么区别?
- Spring框架中的单例Beans是线程平安的吗?
- BeanFactory和FactoryBean的区别和利用场景?
- Spring的代理如何实现?
- JDK代理机制?
AOP和IOC原理?
- AOP和IOC是Spring的精髓局部
AOP:
- AOP能够看作是对OOP的补充,对代码进行横向扩大
- 通过代理模式实现.代理模式有动态代理和动静代理.
- Spring利用的是动静代理,在程序运行过程中将加强代码织入源代码中
IOC: 管制反转
- 将对象的控制权交给Spring框架,用户应用对象无需创立,间接应用即可
- AOP和IOC重点要理解设计思维
Spring怎么解决循环依赖的问题
Spring的循环依赖问题:
- 什么是循环依赖?
- 怎么检测出循环依赖?
- Spring循环依赖有几种形式,应用基于setter属性的循环依赖为什么不会呈现问题?
Bean的生命周期?
dispatchServlet怎么散发工作的?
- 1. 用户发送申请 -> DispatcherServlet: 前端控制器收到申请后本人不进行解决,而是委托给其余解析器进行解决,作为对立的拜访点,进行全局的流程管制
- 2. DispatcherServlet -> HandlerMapping: HandlerMapping将会把申请映射为HandlerExecutionChain对象.HandlerExecutionChain蕴含一个Hander处理器,多个HandlerInterceptor拦截器
- 3. DispatcherServlet -> HandlerAdapter: HandlerAdapter将会将处理器包装为适配器,从而反对多种类型的处理器
- 4. HandlerAdapter -> 处理器性能办法的调用: HandlerAdapter将会依据适配的后果调用真正的处理器的性能解决办法,实现性能解决,并返回一个ModelAndView对象. ModelAndView对象蕴含模型数据.逻辑视图名
- 5. ModelAndView的逻辑视图名 -> ViewResolver: ViewResolver将逻辑的视图名解析为具体的View
- 6. View -> 渲染: View会依据传进来的Model模型数据进行渲染,这里的Model是一个Map数据结构
- 7. 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户
数据库
数据库中的范式有哪些?
- 第一范式: 数据库中的表的所有字段值都是不可分割的原子数据项
- 第二范式: 数据库表中的每一列都和主键相干,而不能只和主键的某一部分相干
- 第三范式: 数据库表中每一列数据都和主键间接相干,不能间接相干
- 范式是为了缩小数据冗余
MySQL给离散度低的字段建设索引会呈现什么问题?
- 重复性强的字段,不适宜增加索引
- MySQL给离散度低的字段,比方性别设置索引,再以性别作为条件查问反而会更慢
一个表可能会波及两个数据结构:
- 数据表: 寄存表中的数据
- 索引
索引:
将一个或几个字段(组合索引)按法则排列起来,再附加上该字段所在行数据的物理地址(位于表中)
- 比方有个字段是年龄,如果须要选取某个年龄段的所有行,那么个别状况下可能须要进行一次全表扫描
- 然而如果以这个年龄段建设一个索引,那么索引会依照年龄值依据特定的数据结构建一个排列,这样在索引中就能迅速定位,不须要进行全表扫描
为什么性别不适宜建设索引呢?
- 因为拜访索引须要有额定的IO开销,从索引中拿到的只是地址,要想真正拜访到数据还是要对表进行一次IO
- 如果要从表中的100万行数据中取几个数据,那么利用索引迅速定位,拜访索引的IO开销就能够忽略不计
- 如果要从标中的100万行数据取50万行数据,再拜访50万次表,加起来的开销并不会比对表进行一次残缺的扫描小
- 如果将性别字段设为聚焦索引,那么必定能放慢大概一半该字段的查问速度
聚焦索引:
- 指的是表自身数据依照哪个字段的值来进行排序
- 聚焦索引不会付出额定IO开销
- 聚焦索引只能有一个
-因而聚焦索引要用到搜寻最频繁的字段上
- 能够依据业务场景须要,将性别和其余的字段建设联结索引. 比方工夫戳,要将工夫戳字段放在性别后面
- MySQL的最左匹配准则?
- MySQL的隔离级别?
- B+,B树的区别?
- MySQL的常见优化和注意事项?
- 数据库慢查问优化思路
MySQL中的log有哪些?别离有什么作用?
- undo log:
- redo log:
- binlog:
- 数据库ACID?
- 数据库事务的隔离级别?
- 数据库的分库分表?
- 分库分表的全局惟一ID如何实现?
数据库中的索引的构造?什么状况下适宜建索引?
数据库中的索引的构造是一种排序的数据结构,数据库的索引是通过B树和变形的B+树实现的
什么状况下不适宜建设索引:
- 对于在查问过程中很少应用或者参考的列
- 对于只有很少数据值的列
- 对于定义为image,text和bit数据类型的列
- 当批改性能远远大于检索性能时
依据零碎本身的环境状况,无效限度线程数量,使得运行成果达到最佳
- 线程次要是通过管制执行线程的数量,超出数量的线程排队等待,期待有工作执行结束,再从队列最后面取出工作执行
MySQL罕用优化?
- SQL优化
- 表构造优化
- 索引优化
- 缓存参数优化
- Redis的数据类型有哪些?
分布式
- CAP实践?
写一个生产者消费者模式?
生产者消费者模式:
synchronized锁住一个LinkedList:
- 生产者: 只有队列不满,生产后往里存
- 消费者: 只有队列不空,生产后往外取
- 两者通过wait() 和notify() 进行协调
- 要思考怎么样提高效率
- 相熟音讯队列设计精要思维及应用
为什么要应用音讯队列MQ?
- 异步解决: 绝对于传统的串行,并行形式,进步了零碎的吞吐量
- 利用解耦: 零碎间通过音讯通信,不必关怀其余零碎的解决
- 流量削峰: 能够通过音讯队列长度管制申请量,能够缓解短时间内高并发申请
- 日志解决: 解决大量日志传输
- 音讯通信: 音讯队列个别都内置了高效的通信机制,因而能够用在纯的音讯通信. 比方实现点对点音讯队列,聊天室等
如何保障音讯队列MQ的高可用?
- 将所有Broker和待调配的Partition排序
- 将第i个Partion调配到第 (i mod n) 个Broker上
- 将第i个Partion的第j个Replica调配到第 ((i+j) mod n) 个Broker上
MQ有哪些常见问题?如何解决这些问题?
音讯队列的程序问题
- 音讯有序指的是能够依照音讯的发送程序来生产
假设生产者产生了2条音讯:M1,M2.假设M1发送到S1,M2发送到S2.如果要保障M1优先于M2被生产,如何保障:
解决方案:
- 保障生产者 - MQSever - 消费者是一对一对一的关系
缺点:
- 并行度会成为零碎的瓶颈,吞吐量不够
- 会呈现更多的异样解决问题: 只有消费者呈现问题,就会导致整个流程梗塞,不得不解决阻塞的问题
能够通过正当的设计或者将问题合成来躲避:
- 不关注乱序的利用理论大量存在
- 队列无序并不意味着音讯无序
音讯的反复问题:
- 造成音讯反复的根本原因: 网络不可达
所以解决这个问题的办法就是绕过这个问题.也就是: 如果生产端收到两条一样的音讯,应该怎么解决?
解决方案:
生产端解决音讯的业务逻辑放弃幂等性
- 只有放弃幂等性,不论来多少条反复音讯,最初解决的后果都一样
- 保障每条音讯都有惟一编号且保障音讯解决胜利与去重表的日志同时呈现
- 利用一张日志表来记录曾经解决胜利的音讯的ID,如果新到的音讯ID曾经在日志表中,那么就不再解决这条音讯
Kafka,ActiveMQ,RabbitMQ,RocketMQ各有什么优缺点?
- Dubbo是什么?次要利用场景?外围性能?
Dubbo的实现过程?
Dubbo节点角色?
Dubbo中的调用关系?
- 服务容器负责启动,加载,运行服务提供者
- 服务提供者在启动时,向注册核心注册本人提供的服务
- 服务消费者在启动时,向注册核心订阅本人所需的服务
- 注册核心返回服务提供者地址列表给消费者,如果有变更,注册核心将基于长连贯推送变更数据给消费者
- 服务消费者,从提供者地址列表中,基于软负载平衡算法,抉择一台提供者进行调用.如果调用失败,再抉择另一台进行调用
- 服务消费者和服务提供者,在内存中累计调用次数和调用工夫,定时每分钟发送统计数据到监控核心
- Dubbo的注册核心集群宕机,发布者和订阅者之间还可能通信吗?
- Dubbo反对哪些协定,每种协定的利用场景,优缺点?
- Dubbo的超时工夫怎么设置?
Dubbo的负载平衡策略有哪些?
Random:
- 随机负载平衡策略,按权重设置随机概率
- 在一个截面上的碰撞概率高,但调用量越大散布越平均,而且按概率使用权重后也比拟平均,有利于动静调整提供者权重
RoundRobin:
- 轮循负载平衡策略,按公约后的权重设置轮循比率
- 存在慢的提供者累积申请的问题
- 比方: 第二台机器很慢,但没有宕机,当申请到第二台机器就会卡住,长此以往,所有的申请都会卡在 调到第二台机器的时候
LeastActive:
- 起码沉闷调用数负载平衡策略,雷同沉闷数的随机调用.沉闷数指的是调用前后计数差
- 使慢的提供者收到更少的申请,因为越慢的提供者的调用前后计数差会越大
ConsistentHash:
- 一致性Hash负载平衡策略,雷同的参数申请总是发到同一提供者
- 当某台提供者宕机时,本来发往该提供者的申请,基于虚构节点,平摊到其余提供者,不会引起激烈变动
- 缺省只对第一个参数Hash,如果要批改,须要批改 < dubbo:parameter key="hash.arguments" value="0,1" />
- 缺省应用160份虚构节点,如果要批改,须要批改< dubbo:parameter key="hash.nodes" value="320" >
Dubbo集群容错策略?
- Failover: 失败主动切换,当呈现失败,重试其余服务器. 通常用于读操作,但重试会带来更长提早. 能够通过设置retries="2" 来设置重试次数,不蕴含第一次
- Failfast: 疾速失败,只发动一次调用,失败立刻报错. 通常用于非幂等性的写操作,比方新增记录
- Failsafe: 失败平安,出现异常时,间接疏忽. 通常用于写入审计日志等操作
- Failback: 失败主动复原,后盾记录失败申请,定时重发. 通常用于音讯告诉操作
- Forking: 并行调用多个服务器,只有一个胜利即返回. 通常用于实时性要求比拟高的读操作,但须要节约更多服务资源,能够通过设置 forks="2"来设置最大并行数
- Broadcast: 播送调用所有提供者,一一调用,任意一台报错即报错. 通常用于告诉所有提供者更新缓存或日志等本地资源信息
Dubbo的动静代理策略?
Dubbo作为RPC框架,首先要实现的就是跨零碎,跨网络的服务调用
生产方和提供方遵循对立的接口定义
- 生产方调用接口时,Dubbo将其转换为对立格局的数据结构
- 通过网络传输,提供方依据规定找到接口实现,通过反射实现调用
生产方获取的是对近程服务的一个代理 Proxy, 提供方因为要反对不同的接口实现,须要一个包装层Wrapper
- 调用过程:
- 生产方的Proxy和提供方的Wrapper得以让Dubbo构建出简单,对立的体系
这种动静代理与包装是通过SPI的插件形式实现的,接口就是ProxyFactory:
@SPI("javassist")public interface ProxyFactory { @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; @Adaptive({Constants.PROXY_KEY}) <T> invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;}
ProxyFactor有两种实现形式:
- 基于JDK的代理实现
- 基于javassist的实现
- ProxyFactory接口上定义了 @SPI("javassist"), 默认为javassist的实现
- 调用过程:
- Dubbo有哪些注册核心?
- Dubbo与Spring之间的关系?
- Dubbo应用的是什么通信框架?
- Dubbo的平安机制是如何实现的?
- Dubbo连贯注册核心和直连的区别?
- Dubbo的通信协议dubbo协定为什么采纳异步繁多长连贯的形式?
- Dubbo的通信协议dubbo协定适用范围和利用场景?
Dubbo反对哪些序列化协定?Hessian?Hessian的数据结构?
- Dubbo序列化: 阿里基于Java的序列化实现
- Hessian2序列化: Hessian是一种跨语言的高效二进制的序列化形式. 这里理论不是原生的Hessian2序列化,而是阿里批改过的Hessian Lite,是Dubbo默认启用的序列化形式
Json序列化: 目前有两种实现:
- 采纳阿里的fastjson库
采纳Dubbo本身实现的简略Json库
- 个别状况下,json这种文本序列化性能不如二进制序列化
- Kryo和FST: Kryo和FST的性能广泛优于Hessian和Dubbo序列化
Hessian序列化和Java默认的序列化区别?
Hessian是一个轻量级的remoting on http工具,采纳Binary RPC协定,很适宜发送二进制数据,同时又具备防火墙穿透能力
- Hessian反对跨语言串行
- Hessian序列化比Java默认的序列化具备更好的性能和易用性
- Hessian序列化反对的语言比拟多
Protoco Buffer是什么?
- Protoco Buffer是谷歌出品的一种轻量并且高效的结构化数据存储格局,性能比Json,XML弱小得多
Protoco的序列化和反序列化简略并且速度快. 起因在于:
- 编码和解码形式简略,只须要简略的数学运算=位移等等
- 采纳Protoco Buffer本身的框架代码和编译器共同完成
Protoco Buffer的数据压缩成果好,即序列化后数据量的体积小. 起因在于:
- 采纳独特的编码方式,比方Varint,Zigzag编码方式等等
- 采纳 T - L - V 数据存储形式,缩小了分隔符的应用并且数据存储得紧凑
注册核心宕机了能够持续通信吗?
- 能够
- Dubbo消费者在利用启动时会从注册核心拉取已注册的生产者的地址接口,并缓存在本地. 每次调用时,依照本地存储的地址进行调用
ZooKeeper有什么用?ZooKeeper原理是什么?
ZooKeeper是一个分布式应用协调系统,曾经利用到了许多分布式我的项目中,用来实现
- 对立命名服务
- 状态同步服务
- 集群治理
- 分布式应用配置项的治理
- 每个Server在内存中存储了一份数据
- ZooKeeper启动时,将从实例中选举一个leader(Paxo协定)
- Leader负责解决数据更新等操作(Zab协定)
- 当且仅当大多数Server在内存中胜利批改数据时,一个更新操作胜利
Netty有什么用?NIO,BIO,AIO有什么用?有什么区别?
- Netty是一个网络通信框架
Netty进行事件处理的流程:
- Channel是连贯的通道,是ChannelEvent的产生者
- ChannelPipeline能够了解为ChannelHandler的汇合
IO的形式通常分为:
- 同步阻塞的BIO
- 同步非阻塞的NIO
- 异步非阻塞的AIO
在应用同步阻塞的BIO的网络应用:
- 如果要同时解决多个客户端申请,或者是在客户端要同时和多个服务器进行通信,就必须应用多线程来解决
同步非阻塞的NIO基于Reactor:
- 当socket有流可读或者可写入socket时,操作系统会相应的告诉援用程序进行解决,利用再将流读取到缓冲区或者写入操作系统
- 这个时候,不是一个连贯就要对应一个解决线程了.而是无效的申请,对应一个线程,当连贯没有数据时,是没有工作线程来解决的
异步非阻塞的AIO与NIO不同:
- 当进行读写操作时,只须要间接调用API的read或者write办法即可
这两种办法均为异步的:
- 对于读操作而言, 当有流可读取时,操作系统会将可读的流传入read办法的缓冲区,并告诉应用程序
- 对于写操作而言,当操作系统将write办法传递的流写入结束时,操作系统被动告诉应用程序
- read或者write办法都是异步的,实现后会被动调用回调函数
为什么要进行零碎拆分?拆分不必Dubbo能够吗?
零碎拆分的分类:
从资源角度:
- 利用拆分
- 数据库拆分
从采纳的先后顺序:
- 程度扩大
- 垂直拆分
- 业务拆分
- 程度拆分
是否应用Dubbo根据理论业务场景来决定:
- 当垂直利用越来越多,利用之间的交互不可避免,将外围业务抽取进去,作为独立的服务,逐步造成稳固的服务中心,使前端利用能更疾速的响应多变的市场需求. 此时,用于进步业务复用以及整合的分布式框架RPC是要害
- 当服务越来越多,容量的评估,小服务资源的节约等问题逐步浮现,此时须要减少一个调度核心基于拜访压力实时治理集群容量,进步集群的利用率. 此时,用于进步机器利用率的资源调度和治理核心SOA是要害
Dubbo和Thrift有什么区别?
- Dubbo反对服务治理,而Thrift不反对
- Thrift是跨语言RPC框架
Redis如何实现分布式锁?
setNX key value
value保障唯一性,防止线程A开释线程B拿到的锁实现分布式锁如果应用setNX命令,那么如果锁的机器宕机了,其余服务怎么拿失去锁?
设置过期工夫
如何来设置过期工夫?先 set key value,再设置过期工夫吗?如果是两条命令,set key value胜利,设置过期工夫失败,一样存在如上问题.那么如何来保障set key value和设置过期工夫的原子操作?
set命令提供了相应的原子操作命令来保障set key value和设置过期工夫的原子操作
Redis是应用的集群吗?如果是集群,当客户端执行setNX时Redis集群,如何做才认为set胜利?一半集群set胜利,就认为胜利吗?还是全副set胜利才认为胜利?
Redis集群应用的是多主多从,当一半以上的主节点set胜利,才算胜利
一半胜利就算胜利,假如Redis集群有a,b,c三个主节点,各有一个从节点,线程A在a,b主节点set胜利,而在c主节点set失败,此时线程A获取到锁,而此时刚好b主节点宕机,刚好数据还没有同步到其从节点,那么此时从节点b'降级到主节点,那么线程B对雷同的key执行set命令来获取锁,在b'和c节点set胜利,这样同样能够获取到锁,这个时候呈现了多个线程获取到同一把锁?
Redis缓存,如何实现更新?
先Delete缓存,再更新DB,延时一段时间再Delete缓存
或者先更新DB,延时一段时间再Delete缓存为什么要延时一段时间?
因为如果线程A先Delete缓存,此时线程B发现缓存中没有数据,则从DB中读出老数据并reload到缓存,线程A更新数据库之后,则缓存与数据库数据库中的数据不统一,因而须要延时一段时间执行删除
如果Delete失败?
重试机制
Redis中的数据结构有哪些?跳表用于哪些场景?
volatile关键字?Lock?
并发编程中的问题:
- 原子性问题
- 可见性问题
- 有序性问题
volatile:
- volatile关键字能保障可见性,只能禁止指令重排序,不能保障原子性
- 可见性只能保障每次读取的是最新的值,然而volatile无奈保障对变量的操作的原子性
- 在生成的会变语句中退出Lock关键字和内存屏障
Lock:
- Lock实现提供了比应用synchronized办法和语句可取得的更宽泛的锁定操作,可能应用更优雅的形式解决线程同步问题
- 用synchronized润饰的办法或者语句块在代码执行完之后锁主动开释,然而应用Lock润饰的办法或者语句须要手动开释锁
Java每次批改都须要从新编译打包部署,有没有更好的额办法?
热部署
过程间通信有哪几种形式?
- 管道: Pipe
- 命名管道: Named Pipe
- 信号: Signal
- 音讯队列: Message
- 共享内存
- 内存映射: Mapped Memory
- 信号量: Semaphore
- 套接口: Socket
Synchronized润饰的办法实例?
Synchronized润饰静态方法,锁定自身不是实例.非静态方法锁定实例
操作系统什么状况下会死锁?
- 死锁: 指多个过程在运行过程中因抢夺资源而造成的一种僵局
产生起因: 竞争资源
- 当零碎中多个过程应用共享资源,并且资源不足以满足需要,会引起过程对资源的竞争而产生死锁
- 过程间推动的程序不当
- 申请和开释资源的程序不当,同样也会产生过程死锁
产生死锁的四个条件
- 互斥条件: 过程独占资源
- 申请与放弃: 过程因申请资源而阻塞时,对已取得的资源放弃不放
- 不剥夺条件: 过程曾经取得资源,在未应用完之前,不能强行剥夺
- 循环期待: 若干过程之间造成头尾相接的循环期待资源关系
如何了解分布式锁?
线上服务器是分布式多台部署的,常常会面临解决分布式场景下数据一致性问题,这是就要利用分布式锁来解决这些问题
- 分布式事务有哪些实现形式?
微服务的架构设计?
JVM
Java类的初始化程序?
Java类的初始化程序:
- 基类动态代码块,基类动态成员变量. 并列优先级,依照代码中呈现的先后顺序执行,并且只有第一次加载时执行
- 派生类动态代码块,派生类动态成员变量. 并列优先级,依照代码中呈现的先后顺序执行,并且只有第一次加载时执行
- 基类一般代码块,基类一般成员变量. 并列优先级,依照代码块中呈现的先后顺序执行
- 基类构造函数.
- 派生类一般代码块,派生类一般成员变量. 并列优先级,依照代码块中呈现的先后顺序执行
- 派生类构造函数.
- 为什么要进行分代?
对办法区和永恒区的了解以及两者的区别?
- 办法区是JVM标准中要求的 ,永恒区是Hotspot虚拟机对办法区的具体实现
- 办法区是标准,永恒区是实现形式(JDK 1.8当前做了扭转)
一个Java类有3个文件,编译后有几个class文件?
- 文件中有几个类,编译后就有几个class文件
局部变量应用前须要显式的赋值,否则编译通过不了,为什么要这样设计?
- 成员变量是能够不经初始化的,在类加载过程的筹备阶段即能够给成员变量赋予默认值.
- 局部变量在应用之前须要显式赋予初始值
- javac不是推断不出不能够这样做,对于成员变量而言,其赋值和取值拜访的先后顺序具备不确定性,对于一个成员变量能够在一个办法调用前赋值,也能够在办法调用后进行赋值,这是运行时产生的,编译器确定不了,交给JVM做比拟适合
对于局部变量而言,局部变量的赋值和拜访程序是确定的,这样设计是一种束缚,尽最大水平缩小使用者犯错的可能性:
- 倘若局部变量能够应用默认值,可能总会无意间遗记赋值,进而导致不可预期的状况呈现
- JVM的内存分区?
- 堆内存的分区以及每个分区的垃圾回收算法?回收器G1,CMS有标记革除,标记整顿法?
- 如何排查Full GC,OOM?
- 线程个数太多会导致OOM,然而这里的线程包含程序的所有线程吗?比方包含pigeon的线程池吗?
JVM中类的加载过程,双亲委派模型中有哪些办法?
类加载过程:
- 加载
- 验证: 验证阶段作用是保障Class文件的字节流蕴含的信息合乎JVM标准,不会给JVM造成挫伤
- 筹备: 筹备阶段为变量分配内存并设置类变量的初始化
- 解析: 解析过程是将常量池内的符号援用替换成间接援用
- 初始化
双亲委派模型中的办法: 双亲委派是指如果一个类收到类加载申请,不会本人先尝试加载,先找父类加载器实现.当顶层启动类加载器示意无奈加载这个类的时候,子类才会本人去加载.当回到最开始的发起者加载器还无奈加载时,并不会向下找,而是抛出ClassNotFound异样
- 启动(Bootstrap)类加载器
- 规范扩大(Extension)类加载器
- 应用程序(Application)类加载器
- 上下文(Custom)类加载器
- 意义是避免内存中呈现多份同样的字节码
- 垃圾收集器理解哪些?
- GC ROOTS包含哪些?
GC算法?什么样的对象算是可回收对象?可达性剖析?CMS收集器?
JVM如何判断一个对象曾经变成可回收的垃圾:
- 援用计数器法: 援用计数器无奈解决循环援用的问题
- 根搜索算法: 从一系列的GC Roots对象开始向下搜寻,搜寻的门路称为援用链.当一个对象到GC Roots之间没有援用链时称为援用不可达.援用不可达的对象被认为是可回收对象
几种垃圾回收器:
- Serial New或者Serial Old: 串行
- Parrallel New: 并行
- Parrallel Scavenge
- Parrallel Old
- G1: 一款并行与并发收集器,并且可建设可预测的进展工夫模型,整体上是基于标记清理,部分采纳复制
- CMS
- CMS收集器是一个以取得最短回收进展工夫为指标的收集器,是一种并发收集器,采纳的是Mark - Sweep算法
- JVM中的GC复制算法是怎么实现的?
JVM分为哪些区?每一个区的作用?
- 办法区(Method): 被所有线程共享,办法区蕴含所有的类信息和动态变量
- 堆(Heap): 被所有的线程共享,寄存对象实例以及数组,Java堆是GC的次要区域
- 栈(Stack): 每一个线程蕴含一栈区,栈中保留一些局部变量
- 程序计数器: 以后线程执行的字节码行指示器
JVM新生代,老年代,长久代.都存储些什么内容?
- 新生代寄存所有新生成的对象
- 老年代寄存的都是一些生命周期较长的对象
- 长久代次要寄存的是Java类的类信息,与垃圾收集要收集的Java对象关系不大
内存溢出和内存泄露?
- 内存溢出: out of memory,程序申请内存时,没有足够的内存
- 内存泄露: 垃圾对象无奈回收,可是应用memory analyzer工具查看泄露
过程与线程?
- 过程: 运行中的程序,具备独立性,动态性,并发性
- 线程: 指过程中的程序执行流
过程与线程的区别:
- 过程间不共享内存
- 创立过程进行资源分配的代价要大得多,所以多线程在高并发的环境中效率高
序列化和反序列化?
- 序列化: 将Java对象转化为字节序列
- 反序列化: 将字节序列转化为Java对象
- 序列化和反序列化次要是为了Java线程间的通信,实现对象传递.只有实现了Serializable或者Externalizable接口类对象才可被序列化
64位JVM中,int的长度是多长?
在JVM中,int类型的变量的长度是一个固定值,与平台无关,4个字节,长度为32位
Java中WeakReference与SoftReference的区别?
Java中一共有四种类型的援用:
- StrongReference
- SoftReference
- WeakReference
- PhantomReference
- StrongReference是Java的默认援用实现,会尽可能长时间的存活于JVM内,当没有任何对象指向时将会被GC回收
- SoftReference会尽可能长的保留援用直到JVM内存不足时才会被回收,通过虚拟机保障.这一个性使得SofeReference非常适合缓存利用
- WeakReference是一个弱援用,当所援用的对象在JVM内不再有强援用时,将被GC回收
WeakReference和SoftReference的区别:
- WeakReference与SoftReference都有利于进步GC和内存的效率
- WeakReference一旦失去最初一个强援用,就会被GC回收
- SoftReference会尽可能长的保留援用直到JVM内存不足时才会被回收,通过虚拟机保障
- JVM内存的划分?
- Java堆的划分?
Java中堆和栈有什么区别?
- Java中的堆和栈属于不同的内存区域,应用目标也不同
- 栈通常用于保留办法帧和局部变量.而对象总是在堆上调配
- 栈通常比堆小,也不会在多个线程之间共享,而堆是被整个JVM所有线程共享
Java堆空间及GC?
Java堆空间:
- 当通过Java命令启动Java过程的时候,会分配内存,内存的一部分用于创立堆空间
- 当程序中创建对象的时候,就从堆空间中分配内存
GC:
- GC是JVM外部的一个过程,回收有效对象的内存用于未来的调配
- 哪些对象会被JVM回收?
网络
TCP如何保障可靠性传输?三次握手过程?
在TCP连贯中,数据流必须以正确的程序送达对方
-TCP可靠性:- 通过程序编码和确认(ACK) 来实现的
TCP连贯是通过三次握手进行初始化的,三次握手的目标是同步连贯单方序列号和确认号并替换TCP窗口大小信息:
- 第一次: 客户端发动连贯
- 第二次: 示意服务器收到了客户端申请
- 第三次: 示意客户端收到了服务器反馈
如何辨认session?
- 在cookie中存储的session id
- HTTP报文构造?
- HTTP状态码?
Linux下的常用命令:
- cd: 用来扭转所在目录. cd / - 转到根目录, cd ~ - 转到用户目录
- ls: 用来查看目录的内容
- cp: 用来拷贝文件. cp sourceFileName targetFileName
- mv: 挪动文件. mv t.txt Document
罕用的Hash算法有哪些?
- 加法Hash: 所谓的加法Hash就是把输出元素一个一个加起来形成最初的后果
- 位运算Hash: 这种类型的Hash函数通过利用各种位运算,比方移位或者异或来充沛的混合输入元素
- 乘法Hash: 33*hash + key.charAt(i)
什么是一致性Hash?
一致性Hash的设计指标是为了解决因特网中的热点(Hot spot)问题,一致性Hash算法提出了在动态变化的Cache环境中,断定Hash算法好坏的四个定义:
- 平衡性 :Balance
- 枯燥性 :Monotonicity
- 分散性 :Spread
- 负载 :Load
表单提交中,get和post的区别?
- get是从服务器获取信息, post是向服务器传信息
- get传送的数据量比拟小, post传递的数据量能够比拟大
- get的安全性比post低
TCP协定和UDP协定有什么区别?
- TCP: Tranfer Control Protocol, 是一种面向连贯的保障传输协定,在传输数据流之前,单方会建设一条虚构的通信道,能够极少过错传输数据
UDP: User DataGram Protocol,是一种无连贯的协定,应用UDP时,每一个数据段都是一个独立的信息,包含残缺的源地址和目的地,在网络上以任何可能的门路达到目的地.因而,是否达到目的地,以及达到目的地的工夫和内容的完整性都不能保障
- TCP比UDP多了建设连贯的工夫.绝对UDP而言,TCP具备更高的安全性和可靠性
- TCP协定传输的大小不限度,一旦连贯被建设,单方能够依照吧肯定的格局传输大量的数据,而UDP是一个不牢靠协定,大小有限度,每次不能超过64K
- Java IO模型有哪几种?
- 同步和异步,阻塞和非阻塞的区别?
- Netty根本介绍