Java面试题以及知识点整理(1)
2017-09-27 16:12
267 查看
1.HashMap和HashTable的区别,及其实现原理。
HashTable底层是用HashMap实现的,与HashMap的区别是,HashTable是按存入顺序排序的,而HashMap不是。HashMap的原理是有一个大的table数组组成,每个数组元素是一个Entry。为了处理冲突,通常会将Entry用链表实现。
2.ArrayList,LinkedList 和Vector的区别和实现原理。
ArrayList是基于数组的可变长数组,因为这个特性,所以它更适合实现get和set;LinkedList是基于双向链表的,所以比较适合实现插入和删除等操作;但以上两个都是非线程安全的,Vector的实现和ArrayList差不多,改进的地方是使用synchronized实现了线程安全。
3.TreeMap和TreeSet区别和实现原理。
其中 TreeMap 是 Map 接口的常用实现类,而 TreeSet 是 Set 接口的常用实现类。TreeSet 底层是通过 TreeMap 来实现的(如同HashSet底层是是通过HashMap来实现的一样),因此二者的实现方式完全一样。而 TreeMap 的实现就是红黑树算法。
相同点:
不同点:
ConcurrentHashMap实现原理(锁分离技术)
4.String和StringBuffer,StringBuilder区别和联系,String为啥不可变,在内存中的具体形态。
String:字符串常量,字符串长度不可变。(引用堆内存的常量池)
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。
StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
5..java中多线程机制,实现多线程的两种方式(继承Thread类和实现Runnable接口)的区别和联系。
一个类只能继承一个父类,存在局限;一个类可以实现多个接口。在实现Runnable接口的时候调用Thread的Thread(Runnable run)或者Thread(Runnablerun,String name)构造方法创建进程时,使用同一个Runnable实例,建立的多线程的实例变量也是共享的;但是通过继承Thread类是不能用一个实例建立多个线程,故而实现Runnable接口适合于资源共享;当然,继承Thread类也能够共享变量,能共享Thread类的static变量;
6..java线程阻塞调用wait函数和sleep区别和联系,还有函数yield,notify等的作用。
wait是Object的方法,sleep是Thread类的方法;
wait让出CPU资源的同时会放弃锁,sleep让出CPU资源的同时不会释放锁;
wait需要notify或者notifyall来唤醒,sleep在沉睡指定时间后,会自动进入就绪状态;
wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。
yield()没有参数。
sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield 方法使当前线程让出CPU占有权,但让出的时间是不可设定的。
yield()也不会释放锁标志。
7. java中的同步机制,synchronized关键字,锁(重入锁)机制,其他解决同步的方volatile关键字ThreadLocal类的实现原理要懂。
TCP/UDP区别,TCP三次握手,SYN攻击
TCP是面向连接的可靠传输,需要三次握手,保证可靠通信;有重传机制;
UDP是无连接的不可靠传输,但是速度快,适用于视频和电话会议等实时应用场景;
TCP三次握手是:SYN=x(SYN_SEND)、ACK=x+1,SYN=y(SYN_RECV)、ACK=y+1(ESTABLISHED);
SYN攻击是:SYN攻击属于DOS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。
检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。
一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固TCP/IP协议栈防范。过滤网关防护主要包括超时设置,SYN网关和SYN代理三种。调整tcp/ip协议栈,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等。
但一般服务器所能承受的连接数量比半连接数量大得多
9.Spring的事务有哪些?
什么是数据库事务:访问并可能改变数据库中个数据项的一个程序执行单元。
实现方式共有两种:编码方式即采用注解的方式(类头的@Transactional为默认事务配置);声明式事务管理方式(bean)。
基于AOP技术实现的声明式事务管理,实质就是:在方法执行前后进行拦截,然后在目标方法开始之前创建并加入事务,执行完目标方法后根据执行情况提交或回滚事务。
声明式事务管理又有两种方式:基于XML配置文件的方式;另一个是在业务方法上进行@Transactional注解,将事务规则应用到业务逻辑中。
10.Java的锁有哪几种?
1、自旋锁:自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。
2、自旋锁的其他种类
3、阻塞锁:常用的有五个状态的锁都是阻塞所。
4、可重入锁:ReentrantLock
5、读写锁:写锁是排他锁,读锁是共享锁。
6、互斥锁
7、悲观锁:在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制。
8、乐观锁:乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
公平锁(Fair):加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
非公平锁(Nonfair):加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待
集合
Collection 接口的接口 对象的集合
├ List 子接口 按进入先后有序保存 可重复
│├ LinkedList 接口实现类 链表 插入删除 没有同步 线程不安全
│├ ArrayList 接口实现类 数组 随机访问 没有同步 线程不安全
│└ Vector 接口实现类 数组 同步 线程安全
│ └ Stack
├ Queue 子接口 队列集合
└ Set 子接口 仅接收一次,并做内部排序
├ HashSet
│ └ LinkedHashSet 插入的次序
└ TreeSet
Map 接口 键值对的集合
├ Hashtable 接口实现类 同步 线程安全 键值非空
├ HashMap 接口实现类 没有同步 线程不安全
│├ LinkedHashMap 插入次序
│└ WeakHashMap
├ TreeMap 基于红黑树,可以返回子树 排序的
└ IdentifyHashMap
Collections 是针对集合类的一个帮助类。提供了一系列静态方法实现对各种集合的搜索、排序、线程完全化等操作。相当于对 Array 进行类似操作的类—— Arrays 。
16.Arraylist如何实现排序
使用Collections.sort()传入ArrayList,会采用默认的方式进行排序(字典序)
使用Collections.sort()传入ArrayList和自己实现Commparator接口的类的对象,实现自定义排序
使用List.sort()传入自己实现Commparator接口的类的对象,实现自定义排序
17.Spring的annotation(注解)如何实现
Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用Annotation,开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证、处理或者进行部署。
12 Java虚拟机的一些参数配置
Trace跟踪参数:
-XX:+PrintGCDetails 打印GC详细信息;
-XX:+PrintGCTimeStamps 打印GC时间戳;
-Xloggc:log/gc.log 指定GC log的位置;
-XX:+PrintHeapAtGC 每一次GC前和GC后,都打印堆信息;
-XX:+TraceClassLoading 监控类的加载;
-XX:+PrintClassHistogram 按下Ctrl+Break后,打印类的信息;
堆的分配参数:
-Xmx20m -Xms5m 指定最大堆和最小堆;
问题1: -Xmx(最大堆空间)和 –Xms(最小堆空间)应该保持一个什么关系,可以让系统的性能尽可能的好呢?
问题2:如果你要做一个Java的桌面产品,需要绑定JRE,但是JRE又很大,你如何做一下JRE的瘦身呢?
-Xmn 官方推荐新生代占堆的3/8,幸存代占新生代的1/10
设置新生代大小
新生代(eden+2*s)和老年代(不包含永久区)的比值
设置两个Survivor区和eden的比值
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump
如果发生了OOM异常,那就把dump信息导出到d:/a.dump文件中。
-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p //p代表的是当前进程的pid
上方参数的意思是说,执行printstack.bat脚本,而这个脚本做的事情是:D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt,即当程序OOM时,在D:/a.txt中将会生成线程的dump。
-XX:PermSize=16m -XX:MaxPermSize:设置永久区的初始空间和最大空间;
栈的分配参数:
Xss 设置栈空间的大小。通常只有几百K;-Xss128K
-XX:+UseParallelGC -XX:ParallelGCThreads=20此配置仅对年轻代有效。
-XX:MaxGCPauseMillis=100 : 设置每次年轻代垃圾回收的最长时间
-XX:+UseCMSCompactAtFullCollection :打开对年老代的压缩。
常见配置汇总
28.Raft协议的leader选举,正常情况下,网络抖动造成follower发起leader选举,且该follower的
Term比现有leader高。集群中所有结点的日志信息当前一致,这种情况下会选举成功吗?
只要term加1之后,之前的leader就作废,这轮选举一定能选出来。我觉得还得看下这个term什么时候会加1,意思就是题目中follower在什么情况下term比之前leader高。因为follower在一个时间段内因为网络波动收不到leader的心跳,他就自动转化为candidate状态且term+1。
13.静态类与单例模式的区别
单例模式比静态类有很多优势:
(1)单例可以继承类,实现接口,而静态类不能(可以集成类,但不能集成实例成员);
(2)单例可以被延迟初始化,静态类一般在第一次加载是初始化;
(3)单例类可以被集成,他的方法可以被覆写;
(4)或许最重要的是,单例类可以被用于多态而无需强迫用户只假定唯一的实例。举个例子,你可能在开始时只写一个配置,但是以后你可能需要支持超过一个配置集,或者可能需要允许用户从外部文件中加载一个配置对象,或者编写自己的。你的代码不需要关注全局的状态,因此你的代码会更加灵活。
观点二:(静态方法)静态方法中产生的对象,会随着静态方法执行完毕而释放掉,而且执行类中的静态方法时,不会实例化静态方法所在的类。如果是用singleton, 产生的那一个唯一的实例,会一直在内存中,不会被GC清除的(原因是静态的属性变量不会被GC清除),除非整个JVM退出了。这个问题我之前也想几天,并 且自己写代码来做了个实验。
观点三:(Good!)
由于DAO的初始化,会比较占系统资源的,如果用静态方法来取,会不断地初始化和释放,所以我个人认为如果不存在比较复杂的事务管理,用singleton会比较好。
14.设计模式原则
设计模式六大原则(1):单一职责原则
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。
解决方案:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。
设计模式六大原则(2):里氏替换原则
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
问题由来:有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。
解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
设计模式六大原则(3):依赖倒置原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
设计模式六大原则(4):接口隔离原则
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
设计模式六大原则(5):迪米特法则
定义:一个对象应该对其他对象保持最少的了解。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:尽量降低类与类之间的耦合。
设计模式六大原则(6):开闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
HashTable底层是用HashMap实现的,与HashMap的区别是,HashTable是按存入顺序排序的,而HashMap不是。HashMap的原理是有一个大的table数组组成,每个数组元素是一个Entry。为了处理冲突,通常会将Entry用链表实现。
2.ArrayList,LinkedList 和Vector的区别和实现原理。
ArrayList是基于数组的可变长数组,因为这个特性,所以它更适合实现get和set;LinkedList是基于双向链表的,所以比较适合实现插入和删除等操作;但以上两个都是非线程安全的,Vector的实现和ArrayList差不多,改进的地方是使用synchronized实现了线程安全。
3.TreeMap和TreeSet区别和实现原理。
其中 TreeMap 是 Map 接口的常用实现类,而 TreeSet 是 Set 接口的常用实现类。TreeSet 底层是通过 TreeMap 来实现的(如同HashSet底层是是通过HashMap来实现的一样),因此二者的实现方式完全一样。而 TreeMap 的实现就是红黑树算法。
相同点:
TreeMap和TreeSet都是有序的集合,也就是说他们存储的值都是拍好序的。 TreeMap和TreeSet都是非同步集合,因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步 运行速度都要比Hash集合慢,他们内部对元素的操作时间复杂度为O(logN),而HashMap/HashSet则为O(1)。
不同点:
最主要的区别就是TreeSet和TreeMap非别实现Set和Map接口 TreeSet只存储一个对象,而TreeMap存储两个对象Key和Value(仅仅key对象有序) TreeSet中不能有重复对象,而TreeMap中可以存在 TreeMap的底层采用红黑树的实现,完成数据有序的插入,排序。
ConcurrentHashMap实现原理(锁分离技术)
4.String和StringBuffer,StringBuilder区别和联系,String为啥不可变,在内存中的具体形态。
String:字符串常量,字符串长度不可变。(引用堆内存的常量池)
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。
StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
5..java中多线程机制,实现多线程的两种方式(继承Thread类和实现Runnable接口)的区别和联系。
一个类只能继承一个父类,存在局限;一个类可以实现多个接口。在实现Runnable接口的时候调用Thread的Thread(Runnable run)或者Thread(Runnablerun,String name)构造方法创建进程时,使用同一个Runnable实例,建立的多线程的实例变量也是共享的;但是通过继承Thread类是不能用一个实例建立多个线程,故而实现Runnable接口适合于资源共享;当然,继承Thread类也能够共享变量,能共享Thread类的static变量;
6..java线程阻塞调用wait函数和sleep区别和联系,还有函数yield,notify等的作用。
wait是Object的方法,sleep是Thread类的方法;
wait让出CPU资源的同时会放弃锁,sleep让出CPU资源的同时不会释放锁;
wait需要notify或者notifyall来唤醒,sleep在沉睡指定时间后,会自动进入就绪状态;
wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。
yield()没有参数。
sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield 方法使当前线程让出CPU占有权,但让出的时间是不可设定的。
yield()也不会释放锁标志。
7. java中的同步机制,synchronized关键字,锁(重入锁)机制,其他解决同步的方volatile关键字ThreadLocal类的实现原理要懂。
TCP/UDP区别,TCP三次握手,SYN攻击
TCP是面向连接的可靠传输,需要三次握手,保证可靠通信;有重传机制;
UDP是无连接的不可靠传输,但是速度快,适用于视频和电话会议等实时应用场景;
TCP三次握手是:SYN=x(SYN_SEND)、ACK=x+1,SYN=y(SYN_RECV)、ACK=y+1(ESTABLISHED);
SYN攻击是:SYN攻击属于DOS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。
检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。
一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固TCP/IP协议栈防范。过滤网关防护主要包括超时设置,SYN网关和SYN代理三种。调整tcp/ip协议栈,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等。
但一般服务器所能承受的连接数量比半连接数量大得多
9.Spring的事务有哪些?
什么是数据库事务:访问并可能改变数据库中个数据项的一个程序执行单元。
实现方式共有两种:编码方式即采用注解的方式(类头的@Transactional为默认事务配置);声明式事务管理方式(bean)。
基于AOP技术实现的声明式事务管理,实质就是:在方法执行前后进行拦截,然后在目标方法开始之前创建并加入事务,执行完目标方法后根据执行情况提交或回滚事务。
声明式事务管理又有两种方式:基于XML配置文件的方式;另一个是在业务方法上进行@Transactional注解,将事务规则应用到业务逻辑中。
10.Java的锁有哪几种?
1、自旋锁:自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。
2、自旋锁的其他种类
3、阻塞锁:常用的有五个状态的锁都是阻塞所。
4、可重入锁:ReentrantLock
5、读写锁:写锁是排他锁,读锁是共享锁。
6、互斥锁
7、悲观锁:在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制。
8、乐观锁:乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
公平锁(Fair):加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
非公平锁(Nonfair):加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待
集合
Collection 接口的接口 对象的集合
├ List 子接口 按进入先后有序保存 可重复
│├ LinkedList 接口实现类 链表 插入删除 没有同步 线程不安全
│├ ArrayList 接口实现类 数组 随机访问 没有同步 线程不安全
│└ Vector 接口实现类 数组 同步 线程安全
│ └ Stack
├ Queue 子接口 队列集合
└ Set 子接口 仅接收一次,并做内部排序
├ HashSet
│ └ LinkedHashSet 插入的次序
└ TreeSet
Map 接口 键值对的集合
├ Hashtable 接口实现类 同步 线程安全 键值非空
├ HashMap 接口实现类 没有同步 线程不安全
│├ LinkedHashMap 插入次序
│└ WeakHashMap
├ TreeMap 基于红黑树,可以返回子树 排序的
└ IdentifyHashMap
Collections 是针对集合类的一个帮助类。提供了一系列静态方法实现对各种集合的搜索、排序、线程完全化等操作。相当于对 Array 进行类似操作的类—— Arrays 。
16.Arraylist如何实现排序
使用Collections.sort()传入ArrayList,会采用默认的方式进行排序(字典序)
使用Collections.sort()传入ArrayList和自己实现Commparator接口的类的对象,实现自定义排序
使用List.sort()传入自己实现Commparator接口的类的对象,实现自定义排序
17.Spring的annotation(注解)如何实现
Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用Annotation,开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证、处理或者进行部署。
12 Java虚拟机的一些参数配置
Trace跟踪参数:
-XX:+PrintGCDetails 打印GC详细信息;
-XX:+PrintGCTimeStamps 打印GC时间戳;
-Xloggc:log/gc.log 指定GC log的位置;
-XX:+PrintHeapAtGC 每一次GC前和GC后,都打印堆信息;
-XX:+TraceClassLoading 监控类的加载;
-XX:+PrintClassHistogram 按下Ctrl+Break后,打印类的信息;
堆的分配参数:
-Xmx20m -Xms5m 指定最大堆和最小堆;
问题1: -Xmx(最大堆空间)和 –Xms(最小堆空间)应该保持一个什么关系,可以让系统的性能尽可能的好呢?
问题2:如果你要做一个Java的桌面产品,需要绑定JRE,但是JRE又很大,你如何做一下JRE的瘦身呢?
-Xmn 官方推荐新生代占堆的3/8,幸存代占新生代的1/10
设置新生代大小
-XX:NewRatio=4
新生代(eden+2*s)和老年代(不包含永久区)的比值
例如:4,表示新生代:老年代=1:4,即新生代占整个堆的1/5 -XX:SurvivorRatio=2(幸存代)
设置两个Survivor区和eden的比值
例如:8,表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump
如果发生了OOM异常,那就把dump信息导出到d:/a.dump文件中。
-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p //p代表的是当前进程的pid
上方参数的意思是说,执行printstack.bat脚本,而这个脚本做的事情是:D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt,即当程序OOM时,在D:/a.txt中将会生成线程的dump。
-XX:PermSize=16m -XX:MaxPermSize:设置永久区的初始空间和最大空间;
栈的分配参数:
Xss 设置栈空间的大小。通常只有几百K;-Xss128K
-XX:+UseParallelGC -XX:ParallelGCThreads=20此配置仅对年轻代有效。
-XX:MaxGCPauseMillis=100 : 设置每次年轻代垃圾回收的最长时间
-XX:+UseCMSCompactAtFullCollection :打开对年老代的压缩。
常见配置汇总
堆设置 -Xms :初始堆大小 -Xmx :最大堆大小 -XX:NewSize=n :设置年轻代大小 -XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 -XX:MaxPermSize=n :设置持久代大小 收集器设置 -XX:+UseSerialGC :设置串行收集器 -XX:+UseParallelGC :设置并行收集器 -XX:+UseParalledlOldGC :设置并行年老代收集器 -XX:+UseConcMarkSweepGC :设置并发收集器 垃圾回收统计信息 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename 并行收集器设置 -XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。 -XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间 -XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 并发收集器设置 -XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。 -XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
28.Raft协议的leader选举,正常情况下,网络抖动造成follower发起leader选举,且该follower的
Term比现有leader高。集群中所有结点的日志信息当前一致,这种情况下会选举成功吗?
只要term加1之后,之前的leader就作废,这轮选举一定能选出来。我觉得还得看下这个term什么时候会加1,意思就是题目中follower在什么情况下term比之前leader高。因为follower在一个时间段内因为网络波动收不到leader的心跳,他就自动转化为candidate状态且term+1。
13.静态类与单例模式的区别
单例模式比静态类有很多优势:
(1)单例可以继承类,实现接口,而静态类不能(可以集成类,但不能集成实例成员);
(2)单例可以被延迟初始化,静态类一般在第一次加载是初始化;
(3)单例类可以被集成,他的方法可以被覆写;
(4)或许最重要的是,单例类可以被用于多态而无需强迫用户只假定唯一的实例。举个例子,你可能在开始时只写一个配置,但是以后你可能需要支持超过一个配置集,或者可能需要允许用户从外部文件中加载一个配置对象,或者编写自己的。你的代码不需要关注全局的状态,因此你的代码会更加灵活。
观点二:(静态方法)静态方法中产生的对象,会随着静态方法执行完毕而释放掉,而且执行类中的静态方法时,不会实例化静态方法所在的类。如果是用singleton, 产生的那一个唯一的实例,会一直在内存中,不会被GC清除的(原因是静态的属性变量不会被GC清除),除非整个JVM退出了。这个问题我之前也想几天,并 且自己写代码来做了个实验。
观点三:(Good!)
由于DAO的初始化,会比较占系统资源的,如果用静态方法来取,会不断地初始化和释放,所以我个人认为如果不存在比较复杂的事务管理,用singleton会比较好。
14.设计模式原则
设计模式六大原则(1):单一职责原则
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。
解决方案:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。
设计模式六大原则(2):里氏替换原则
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
问题由来:有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。
解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
设计模式六大原则(3):依赖倒置原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
设计模式六大原则(4):接口隔离原则
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
设计模式六大原则(5):迪米特法则
定义:一个对象应该对其他对象保持最少的了解。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:尽量降低类与类之间的耦合。
设计模式六大原则(6):开闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
相关文章推荐
- 【Java&Android】名企面试题和涉及知识点整理
- Java基础面试题知识点整理
- java,html5+css3以及javascript面试题------自己面试的时候遇到的面试题,所以整理一下
- Java知识点及其面试题整理二
- Java知识点及其面试题整理三
- Java相关笔试题以及面试题的链接整理(不断更新)
- 整理最全的Android开发工程师面试题,面试题详解。java、Android程序员
- java基础知识点、面试选择题归纳整理
- Java知识点整理:第五章:类的声明,构造方法,方法,继承中的构造器,对象实例化过程
- 前端面试题整理-------HTML/CSS部分----小知识点
- 【Java多线程与并发】知识点整理(追加中)
- Java基础面试题整理
- 2017年Java面试题整理
- 【Java】入门知识点整理-1
- 整理的Java面试题
- 2017常见的50道java基础面试题整理(附答案)
- java基础知识记录--基本语法 (摘自张孝祥整理java面试题)
- Android 名企面试题及涉及知识点整理
- Java面试题整理
- JAVA面试题整理