Java基本知识

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数据不会释放)

原文地址:https://www.cnblogs.com/wuan90/p/11227400.html