携程一面 4.7
1.架构
2.分库分表怎么设计的?如何分库分表的?
hash取模 数据均匀性
3.列举一些常见的集合类 和它的数据结构和简单的实现原理
4.hashmap和currentMap有什么区别
5.线程池
6.线程数怎么设置
7.jvm内存模型
8.对象的生命周期
在JVM的运行空间中,对象的生命周期大概可以分为7各阶段:
创建阶段(creation)
应用阶段(Using)
不可见阶段(invisible)
不可到达阶段(Unreachable)
可收集阶段(Collected)
终结阶段(Finalized)
释放阶段(Free)
创建阶段(creation)
在创建对象阶段,系统要通过下面步骤,完成对象的创建过程:
1).为对象分配存储空间
2).开始构造对象
3)递归调用其他超类的构造方法(递归调用该类所扩展的所有父类的构造方法)
4)进行对象实例化与变量初始化
5)指向构造方法体
创建规则:
在创建对象时,系统做的一些处理工作,其中某些过程与应用的性能密切相关,因此在创建对象时,我们需要遵循一些基本的规则:
1.非必须条件下,尽量避免在循环体中创造对象,即使该对象占用空间不大(不要在死循环中创建对象)
2.尽量及时使对象符合垃圾回收标准
3.不要采用过深的继承层次
4.访问本地变量由于访问类中的变量
1.避免在循环体中创造对象:
for (int i = 0; i < 10000; ++i) { Object obj = new Object(); System.out.println("obj= "+ obj); }
采用该方式,会在内存里保存一份对改该对象的引用,而不像上面的第一张编写方式中的代码会产生大量对象应用,浪费大量空间,增大系统垃圾回收的负荷
for (int i = 0; i < 10000; ++i){ obj = new Object(); System.out.println("obj= "+ obj);}
此外,不要对一个对象进行多次初始化,这同样会造成大量的内存开销
public class A { private Hashtable table = new Hashtable ();
public A() { table = new Hashtable(); // 将Hashtable对象table初始化了两次 }
}
正确的方式:
public class B { private Hashtable table = new Hashtable ();
public B() { }
}
在程序设计中切记“勿以恶小而不为”的古训,否则我们开发出来的也是优化差,低效的应用
应用阶段
在对象创建结束之后,通常进入的就是应用阶段。这个阶段是对象表现自身能力的阶段,也就是说对象的应用阶段,是对象展现自己,被使用的阶段,在此阶段,对象有以下特征
- 系统至少维护着对象的一个强引用
- 所有对该对象引用的都是强引用(除非我们显式的使用了:软,弱,虚引用)
强引用(new一个对象,该对象就是强引用)
我们平日里面的用到的new了一个对象就是强引用,例如 Object obj = new Object();
当JVM的内存空间不足时,宁愿抛出OutOfMemoryError(溢出异常)使得程序异常终止也不愿意回收具有强引用的存活着的对象!
只要强引用指向一个目标(a=b,a指向b目标,那么a就是强引用),垃圾处理器就不会回收这个对象。显示的设置0,null或超出对象的生命周期,此时就可以回收这个对象。具体回收时机还是要看垃圾回收策略,在不用对象的实际将引用赋值为null,能够帮助垃圾回收器回收对象
软引用(图片缓存,网页缓存)
软引用的主要特点时具有较强的应用功能,只有当内存不够的时候,才会回收这类内存。另外,这些引用对象话能保证在java抛出OutOfMemory(内存溢出)之前,设置为null。它可以用于实现一些常用的资源的缓存实现Cache功能,保证最大限度的使用内存而不引起OutOFMemory。
软可到达对象的所有软引用都要保证在OutOfMemoryError之前被清除,否者清除软引用的时间或清楚不同的对象的一组此类引用的顺序将不受约束。然而,虚拟机不鼓励清楚最近访问或使用的软引用
import java.lang.ref.SoftReference; … A a = new A(); … // 使用 a … // 使用完了a,将它设置为soft 引用类型,并且释放强引用; SoftReference sr = new SoftReference(a); a = null; … // 下次使用时 if (sr!=null) { a = sr.get(); } else{ // GC由于内存资源不足,可能系统已回收了a的软引用, // 因此需要重新装载。 a = new A(); sr=new SoftReference(a); }
软引用使得java可以更好的管理内存,稳定系统。防止系统内存溢出,避免崩溃。因此在处理一些占用内存较大,而且生命周期较长,但是用并不频繁的对象时因该尽量应用该技术。
在软引用对象被回收时可以重新被创建。减少内存占用,提高了内存的使用效率,提高系统稳定性。
但是有时候在某些软引用会较低应用的运行效率和性能。例如某些对象的初始化过程较为耗时或者对象的状态在程序运行中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦
3.弱引用(临时数据,内部类引用外部类)
弱引用(weak Reference)对象与软引用引用对象最大的不同就是:
- GC回收时,需要通过算法检查是否回收软引用引用对象。
- 对于弱引用引用对象,GC总是回收
因此weak引用对象会更容易,更快被GC回收。
虽然GC在运行时一定回收weak引用对象,但是复杂关系的weak对象常常需要好几次回收才能完成。weak引用对象存贮在map数据结构中,引用占用内存空间较大的对象,一旦对象的强引用为null时这个引用就不存在了,GC可以快速的回收这个给对象的空间
import java.lang.ref.WeakReference; … A a = new A(); … // 使用 a … // 使用完了a,将它设置为weak 引用类型,并且释放强引用; WeakReference wr = new WeakReference (a); a = null; … // 下次使用时 if (wr!=null) { a = wr.get(); } else{ a = new A(); wr = new WeakReference (a); }
弱引用技术主要适用于实现无法防止其键(或值)被回收的规范化映射,另外,弱引用分为“短弱引用”和“长弱引用”
区别在于长弱引用在对象的Finalize方法被GC调用之后依然追踪对象,基于安全考虑,不推荐使用长弱引用
虚引用
如果一个对象与虚引用关联,则根没有引用与之关联一样。
虚引用的用途较少,主要用于辅助finalize函数的使用,Phantom对象指一些执行完了finalize函数,并且为不可达对象,但是还没有被GC回收的对象,这种对象可以辅助finalize进行一些后期的回收工作。
实现程序设计中很少使用软引用或者虚引用,使用软引用的情况较多,因为软引用可以加速JVM堆垃圾的回收速度。可以维护系统的运行安全,防止溢出的发展
不可视阶段
一个对象经历过应用阶段之后,那么该对象就处于不可视阶段,我们在其他区域代码中不再使用它,他的强引用已经消失,
public void process () { try { Object obj = new Object(); obj.doSomething(); } catch (Exception e) { e.printStackTrace(); } while (isLoop) { // ... loops forever // 这个区域对于obj对象来说已经是不可视的了 // 因此下面的代码在编译时会引发错误 obj.doSomething(); } }
如果一个对象被使用完应该主动将其设置为null可以在上方的代码下添加obj=null;强制将obj设置为空,可以帮助jvm及时发现这个垃圾对象,并及时回收资源
不可到达阶段
该阶段的对象,在虚拟机中所管理的对象引用根本集合中再也找不到直接或简介的强引用,这些对象通常是指所有线程栈中的临时变量,所有已装载在的类的静态变量或者对本地代码接口的引用。
这些对象都是要被回收的预备队下,但此时该对象并不能被垃圾回收器直接回收,其实所有垃圾回收算法面临的问题都是相同的——找出由分配器分配的,但是应用程序不可到达的内存块
最终释放阶段
这事对象生命周期的最后一个阶段。
当对象处于这个阶段的时候,可能处于下面三种情况:
(1)垃圾回收器发现该对象已经不可到达。
(2)finalize方法已经被执行。
(3)对象空间已被重用。
当对象处于上面的三种情况时,该对象就处于可收集阶段、终结阶段与释放阶段了。虚拟机就可以直接将该对象回收了
9.cpu占比过高
10.cpu过高
11.内存泄漏
12.事务级别
13.ACID
14.sql优化
15.编码规范 代码注意哪些 可拓展性,可维护性
算法题 实现一个支持对象的栈
#软件开发2024笔面经#