1、ReentrantLock和Synchronized的区别,以及实现原理
ReentrantLock是java代码实现,Synchronized是字节码实现,ReentrantLock可使用公平锁、可根据Condition分组唤醒线程、而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程,ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。
ReentrantLock内部实现原理:AbstractQueuedSynchronizer简称AQS,AQS维护一个volatile int state字段和双向队列来实现。AQS详解
Synchronized实现原理:代码块时是在字节码中加入moniterenter和moniterexit,当执行到moniterenter时会获取锁定对象的锁,方法时是在Class文件的方法表中将该方法的access_flags存放ACC_SYNCHRONIZED。锁定的对象的加锁是通过对象头MARKWORD中指向的当前对象的ObjectMoniter来加锁。Synchronized的内部实现原理以及Moniter实现原理。
2、jvm问题排查
1、程序hung住:线程死锁、线程堵塞。通过jps获取当前进程id,jstack -l pid,出现BLOCKED、deadlock。
2、CPU100%: jps查看pid,top -H -p pid查看cpu最高的线程id,jstack pid> a.log 然后在a.log中搜索线程id的16进制。
3、频繁full gc:可能是oom。jmap -dump:format=b,file=/home/admin/dump.bin pid导出堆的信息,用VisualVM进行分析。jstat -gcutil pid查看gc情况。一次线上OOM排查经过
3、java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
偏向锁适用于单个线程时提高性能,轻量级锁适用于多个线程交替执行。
偏向锁:首先CAS修改线程id为当前线程id,失败并且线程id不是当前线程,在安全点判断持有锁的线程是否存在,不存在标示为未锁定,存在升级为轻量级锁。
轻量级锁:复制MARKWORD到LOCK record里,CAS修改线程id为当前线程id,失败并且线程id不是当前线程,进入自旋CAS获取,获取失败升级为重量级锁。执行结束,复制的那份MARK word用CAS替换,如果失败也进入重量级锁。java 中的锁 关于偏向锁、轻量级锁将的不是很好,参考这个《JVM源码分析之synchronized实现》
4、堆外内存使用以及回收机制
堆外内存时jvm以外的内存,当建立一个堆外内存的时候会在堆中创建一个Cleaner对象对应DirectByteBuffer,当DirectByteBuffer对象被回收时,把cleaner对象放到ReferenceQueue队列,在FULL gc时会调用ReferenceQueue中所有Cleaner对象的clear方法。也可以手动获取Cleaner对象,并调用clear方法进行回收。堆外内存的回收机制分析
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 200);//200M堆外内存
((DirectBuffer)buffer).cleaner().clean();//手动回收
5、强引用、软引用、弱引用、虚引用
强引用:只要引用存在永不回收。比如new 一个对象。
软引用:内存溢出之前进行回收。SoftReference。应用:缓存
弱引用:第二次垃圾回收时回收。WeakReference。
虚引用:垃圾回收时回收。PhantomReference。
6、动态代理
jdk动态代理:被代理类必须实现了接口。原理实现InvocationHandler接口,内部还是使用的反射。
cglib代理:被代理类不时必须实现接口,性能比不上jdk,通过继承被代理类来实现。需要实现MethodInterceptor接口。
7、ArrayList、Vector、HashSet、HashTable默认容量和扩容
ArrayList:默认容量:10 扩容增量:1.5*原数组长度
Vector:默认容量:10 扩容增量:2*原数组长度
HashSet:默认容量:16 扩容增量:2*原数组长度
HashTable:默认11 扩容增量:2*原数组长度+1
8、浅拷贝和深拷贝的区别
浅拷贝:只拷贝当前对象,而当前对象引用的其它对象还是引用同一个对象。
深拷贝:不仅拷贝当前对象还拷贝当前对象引用的对象。
A a = new A();A b =a;//只是引用 不叫拷贝
9、线程的五种状态和线程池的五种状态以及状态流转
线程五种状态:新建New、就绪Runnable、运行Running、阻塞Blocked及死亡Dead。
线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated。
网友评论