1. CGLIB动态代理:
1 Enhancer enhancer = new Enhancer(); 2 enhancer.setSuperclass(SampleClass.class); 3 enhancer.setCallback(new MethodInterceptor() { 4 @Override 5 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 6 System.out.println("before method run..."); 7 Object result = proxy.invokeSuper(obj, args); 8 System.out.println("after method run..."); 9 return result; 10 } 11 }); 12 SampleClass sample = (SampleClass) enhancer.create(); 13 sample.test();
注意:动态代理不能拦截final方法
jdk动态代理:需要有顶层接口才能使用
cglib动态代理:可以直接代理类,使用字节码技术,不能对 final类进行继承
2. 字符串常量池:
注意:在jdk1.7之前,字符串常量存储在方法区的PermGen Space。在jdk1.7之后,字符串常量重新被移到了堆中
a. String a1 = "aa"; //先判断“aa”是否在常量池,如果在则直接引用,否则,在常量池中创建“aa”
b. String a2 = new String("aa"); //在堆上创建字符串对象,如果常量池不存在aa,则常量池中创建aa
c. String a3 = "a" + "a"; //jvm编译时会自动优化为String a3 = "aa";
d. String a4 = a3.intern(); //intern方法会去常量池中查找该对象,如果对象存在则返回常量池对象,否则在常量池中创建对象(jdk7则在常量池中生成字符串的引用)
备注:JDK 1.7后,intern方法还是会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,这一点与之前没有区别,区别在于,如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。
e. String a5 = new String("AA") + new String("BB"); //在堆上创建对象AA、BB和AABB,在常量池上创建常量AA和BB
f. String a6 = "a1" + "a2"; //在常量池中创建“a1”、“a2”、“a1a2”
3. HashMap死锁原因:
HashMap在进行扩容时,需要将原链表内容拷贝到新的数组中,拷贝前A->B->C的链表,拷贝后会变为C->B->A,在多线程并发的情况下会出现环形链路,如果再调用get方法则会出现死循环
4. ReentrantLoc相关知识:
在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。
void lock(); //获取锁,若当前lock被其他线程获取;则此线程阻塞等待lock被释放
boolean tryLock(); //尝试获取锁,如果获取成功,则返回true;
void unlock(); //释放锁(加锁次数必须与解锁次数相同)
Condition newCondition(); //返回一个绑定该lock的Condtion对象
ReentrantLock 与 synchronized 的比较
相同:ReentrantLock提供了synchronized类似的功能和内存语义。
不同:
(1)与synchronized相比,ReentrantLock提供了更多,更加全面的功能,具备更强的扩展性。例如:时间锁等候,可中断锁等候,锁投票。
(2)ReentrantLock还提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合(下面会阐述Condition)。
(3)ReentrantLock提供了可轮询的锁请求。它会尝试着去获取锁,如果成功则继续,否则可以等到下次运行时处理,而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以相比synchronized而言,ReentrantLock会不容易产生死锁些。
(4)ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在同一个synchronized块结构中获取和释放。注:ReentrantLock的锁释放一定要在finally中处理,否则可能会产生严重的后果。
(5)ReentrantLock支持中断处理,且性能较synchronized会好些。
参考:https://www.cnblogs.com/xiaoxi/p/7651360.html
https://blog.csdn.net/u010013573/article/details/87266678
5. 序列化:
对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。
6. 多线程控制:
CountDownLatch 可以实现某个任务等待其他几个任务完成后执行
CyclicBarrier 可以实现让一组线程等待至某个状态之后再全部同时执行
Semaphore 用来控制同时访问的线程个数
public
void
acquire() 用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可
public
void
release() 用来释放许可。注意,在释放许可之前,必须先获获得许可
7. ThreadLocal实现原理:
在类Thread中持有一个ThreadLocal.ThreadLocalMap对象,ThreadLocal对象先获取到当前线程的ThreadLocalMap对象,然后set/get对应的值
InheritableThreadLocal 能够继承父线程的数据(注意:线程池的情况下InheritableThreadLocal数据不会释放)