从写一个单例开始究竟能问多深及终极解决方案

ddatsh

dev #java

写一个线程安全的单例模式的例子

线程安全的实现有很多种,根据业务场景可以new一个实例作为私有静态成员变量,这样程序一启动,实例就生成,私有化构造函数,利用公用的静态函数getInstance返回实例

这种预加载的是能保证线程安全的但是如果不是确定会被使用,会造成内存的浪费,所以可以将实例放到私有静态类中作为成员变量

写一种利用锁机制来保证的懒加载方法

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

从这个例子上我能想到的知识点主要有三个

是否真的理解自己写的代码

将类的构造方法私有起来,外部调用进行初始化的时候只能通过调用getSingleton这个静态方法来获得实例,静态方法是整个Java虚拟机中只有一个实例

在创建的时候首先进行非空判断,这时候如果实例不存在,对整个类进行加锁同步,为了避免过程中非空状态的改变,同步块内再进行一次判断,如果不存在实例则创建实例返回

使用volatile关键字,下次访问这个方法就能直接看到实例的最新非空状态,直接返回实例

通过new对象创建出来的,还可不可以采用别的方法来创建对象

class类的newInstance方法,Constructor构造器类的newInstance方法,克隆方法和反序列法方法

类加载的时候,自己定义了一个类和java自己的类类名和命名空间都一样,JVM加载的是哪一个呢?

调用的是java自身的,根据双亲委派模型,最委派Bootstrap的ClassLoader来加载,找不到才去使用Extension的ClassLoader,还找不到才去用Application的ClassLoader,这种机制利于保证JVM的安全

java的反射机制是什么概念?

在运行状态中,对于任何一个类,都能够知道它所有的属性和方法

对于任何一个对象,都能够调用它的任何一个方法和属性。这种动态的获取信息和动态调用对象的方法的功能就是java的反射机制。它是jdk动态代理的实现方法

其他的动态代理实现?

还有cglib动态代理

两种动态代理哪个比较好呢?

spring AOP 同时使用了这两种动态代理,因为他们各有优劣

jdk动态代理是利用java内部的反射机制来实现,在生成类的过程中比较高效

cglib动态代理则是借助asm来实现,可以利用asm将生成的类进行缓存,所以在类生成之后的相关执行过程中比较高效

但是jdk的动态代理前提是目标类必须基于统一的接口,所以有一定的局限性