单列模式的四种写法

1、懒汉模式(线程不安全的)

public class SingletonTest01 {

    public static void main(String[] args) {
        new Thread(){
            public void run(){
                System.out.println(MySingleton01.getInstance());
            }
        }.start();
        new Thread(new Runnable(){
            public void run() {
                System.out.println(MySingleton01.getInstance());
            }
        }).start();
    }
}
//懒汉模式(是线程不安全的),如果多线程处理时,需加synchronized进行处理
class MySingleton01{
    //创建一个私有的静态的类(不实例化)
    private static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
    //创建私有的构造方法
    private MySingleton01(){}
    //创建一个开放的实例化方法,供外界获取对象
    public static MySingleton01 getInstance(){
        if(mySingleton01==null){
            try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
            mySingleton01 = new MySingleton01();
            return mySingleton01;
        }else{
            return mySingleton01;
        }
    }
}

此处mySingleton01用volatile修饰会更好
改为线程安全的:
class MySingleton01{
    //创建一个私有的静态的类(不实例化)
    private volatile static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
    //创建私有的构造方法
    private MySingleton01(){}
    //创建一个开放的实例化方法,供外界获取对象
    public static MySingleton01 getInstance(){
        if(mySingleton01==null){//Java 中的双重检查技术(Double-Check)
            synchronized (MySingleton01.class) {
                try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                if(mySingleton01==null){
                    mySingleton01 = new MySingleton01();
                }
            }       
            return mySingleton01;
        }else{
            return mySingleton01;
        }
    }
}

2、饿汉模式(线程安全的)

public class SingletonTest02 {
    public static void main(String[] args) {
        new Thread(){
            public void run(){
                System.out.println(MySingleton02.getInstance());
            }
        }.start();
        new Thread(new Runnable(){
            public void run() {
                System.out.println(MySingleton02.getInstance());
            }
        }).start();
    }
}
//饿汉模式(是线程安全的)
class MySingleton02{
    //创建一个私有的静态的类(实例化)
    private static MySingleton02 mySingleton=new MySingleton02();
    //创建私有的构造方法
    private MySingleton02(){}
    //创建一个开放的实例化方法,供外界获取对象
    public  static MySingleton02 getInstance(){
        return mySingleton;
    }
}

3、延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,推荐使用)

public class SingletonTest03 {

    public static void main(String[] args) {
        new Thread(){
            public void run(){
                System.out.println(MySingleton03.getInstance());
            }
        }.start();
        new Thread(new Runnable(){
            public void run() {
                System.out.println(MySingleton03.getInstance());
            }
        }).start();
    }
}
//延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,只有在调用getInstance方法后,才会实例化对象)
class MySingleton03{
    //创建一个私有的静态的内部类,持有对象(实例化)
    private static class MySingleton03Holder{
        private static MySingleton03 mySingleton=new MySingleton03();
    }
    //创建私有的构造方法
    private MySingleton03(){}
    //创建一个开放的实例化方法,供外界获取对象
    public  static MySingleton03 getInstance(){
        return MySingleton03Holder.mySingleton;
    }
}

4、枚举类型实现单例(除了不能延迟加载,其它特性都是极好的,是最安全的,是所有写法中唯一一种不能通过反射或反序列化破解单例的写法,推荐使用)

public class SingletonTest04 {
    public static void main(String[] args) {
        System.out.println(MySingleton04.INSTANCE==MySingleton04.INSTANCE);
        MySingleton04 m1 = MySingleton04.INSTANCE;
        MySingleton04 m2 = MySingleton04.INSTANCE;
        m1.say();
        m1.say();
        System.out.println(m2.getI());
    }
}

enum MySingleton04{//枚举类型
    INSTANCE;
    private int i=0;
    public void say(){
        System.out.println("Hello World !!!");
        i++;
    }
    public int getI() {
        return i;
    }
}

5、通过反射的方式破解单例模式

public class SingletonTest05 {
    public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
        System.out.println(MySingleton05.getInstance());
        System.out.println(MySingleton05.getInstance());
        //通过反射的方式直接调用私有构造器
        Class clazz =(Class) Class.forName("com.primeton.singleton.MySingleton05");
        Constructor c =clazz.getDeclaredConstructor(null);
        c.setAccessible(true);
        MySingleton05 mySingleton1 = c.newInstance(null);
        MySingleton05 mySingleton2 = c.newInstance(null);
        System.out.println(mySingleton1);
        System.out.println(mySingleton2);
    }
}
class MySingleton05{
    //创建一个私有的静态的类(实例化)
    private static class MySingleton03Holder{
        private static MySingleton05 mySingleton=new MySingleton05();
    }
    //创建私有的构造方法
    private MySingleton05(){}
    //创建一个开放的实例化方法,供外界获取对象
    public  static MySingleton05 getInstance(){
        return MySingleton03Holder.mySingleton;
    }
    public static void say(){
        System.out.println("Hello World !!!");
    }
}

结果:
com.primeton.singleton.MySingleton05@1cc2ea3f
com.primeton.singleton.MySingleton05@1cc2ea3f
com.primeton.singleton.MySingleton05@40a0dcd9
com.primeton.singleton.MySingleton05@1034bb5
结论:通过该方式让该单例类产生了多个对象

6、通过序列化与反序列化的方式破解单例模式(被破解的单例需实现了Serializable接口才行)

public class SingletonTest06 {
    public static void main(String[] args) throws Exception {
        System.out.println(MySingleton05.getInstance());
        System.out.println(MySingleton05.getInstance());
        //通过序列化与反序列化的方式破解单例模式
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D://ceshi.txt")));
        oos.writeObject(MySingleton06.getInstance());
        oos.flush();
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D://ceshi.txt")));
        MySingleton06 mySingleton1 = (MySingleton06) ois.readObject();
        System.out.println(mySingleton1);
    }
}
class MySingleton06 implements Serializable{
    //创建一个私有的静态的类(实例化)
    private static class MySingleton03Holder{
        private static MySingleton06 mySingleton=new MySingleton06();
    }
    //创建私有的构造方法
    private MySingleton06(){}
    //创建一个开放的实例化方法,供外界获取对象
    public  static MySingleton06 getInstance(){
        return MySingleton03Holder.mySingleton;
    }
    public static void say(){
        System.out.println("Hello World !!!");
    }
}
结果:
com.primeton.singleton.MySingleton05@3fbefab0
com.primeton.singleton.MySingleton05@3fbefab0
com.primeton.singleton.MySingleton06@4d546e25
结论:通过该方式让该单例类产生了多个对象

你可能感兴趣的:(单列模式的四种写法)