GOF23的一些总结(一)

来源:互联网 发布:激光点云数据处理软件 编辑:程序博客网 时间:2024/05/29 03:12

1、单利模式:
核心作用:保证一个类中只有一个实例(对象),并且提供一个访问该实例的全局访问点。(不管你启动了多少个,始终只有一个)
比如windows的TaskManager,Recycle Bean。
优点:单利只生成一个实例,减少了系统性能的开销,减少系统性能开销。可以在系统设置全局访问点,优化共享资源访问。
常见的五种单利模式实现方式:
主要:
饿汉式:(线程安全,调用效率高。但是,不能延时加载。)
懒汉式:(线程安全,调用效率不高,但是,可以延时加载。)
-其他:
双重检测锁式(由于JVM低层内部模型原因,偶尔会出问题。不建议使用)
静态内部类式(线程安全,调用效率高。但是,可能延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式

public class SingletonHungry{    private static /*final*/ SingletonHungry instance = new SingletonHungry();//类初始化的时候加载(没有延时)    private SingletonHungry(){    }    //类加载器加载时本身线程安全。    public static SingletonHungry getInstance(){                return instance;    }}

懒汉式

public class SingletonLazzy{    //类初始化的时候不实例化对象    private static SingletonLazzy instance;    //私有化构造方法    private SingletonLazzy(){    }    //方法同步,调用效率低    private static synchronized SingletonLazzy getInstance(){        if(instance==null){            instance=new SingletonLazzy;        }        return instance;    }}

双重检测锁机制

//由于类加载和JVM会调整顺序,所以仅做参考public class SingletonCheck{    private static SingletonCheck instance=null;    public static SingletonCheck getInstance(){            if(null==instance){                SingletonCheck sc;                    synchronized (SingletonCheck.class){                    sc=instance;                        if(null=sc){                            synchronized(SingletonCheck.class){                                if(sc==null){                                    sc=new SingletonCheck();                                }                            }                            instance=sc;                        }                }            }            return instance;        }    private SingletonCheck(){    }}

静态内部类实现方式

//线程安全,调用效率高,并且实现了延时加载public class SingletonStaticInnerClass{private static class SingletonClassInstance{    private static final SingletonStaticInnerClass instance = new SingletonstaticInnerClass();}private static SingletonStaticInnerClass getInstanc(){    return SingletonClassInstance.instance;}private SingletonStaticInnerClass(){}}

通过枚举实现单利模式

//避免了反射和序列化的漏洞,调用效率比较高,没有懒加载public enum SingletonEnum{    //这个枚举,本身就是单利模式    INSTANCE;    //添加自己需要的操作    public void  singletonOpreation(){    }}

测试反射和反序列化破解(除枚举外的)单利模式

public class Client{    public sttic void main (String[]args){        Class<Singleton> clazz=(Class<Singleton>)Class.forName("");        Constructor<Singleton> c = clazz.getDeclaredConstructor(null);        c.setAccessible(true);//跳过检测        Singleton s3 = c.newInstance();    }}

反破解跳过(除枚举外的其中饿汉式)私有权限检测方式

public class Singleton{    private static Singleton instance =new Singleton();    private Singleton(){//破解反射        if(null!=instance){            throw new RunTimeException();        }    }    public static Singleton getInstance(){        return instance;    }}

测试反序列化破解序列化的单利

public class Client2{    public static void main (String[]args){        Singleton s1 = Singleton.getInstance();        try{        FileOutputStream fos =new FileOutputStream("d:/a.txt");        ObjectOutputStream oos = new ObjectOutputStream(fos);        oos.writeObjec(s1);        }catch{            e.printlnStackException();        }finally{            oos.close();            fos.close();        }        ObjectInputStream ois  = new ObjectInputStream(new FileInputStream("d:/a.txt"));            Singleton s3=(Singleton)ois.readObject();            System.out.println(s3);    }}

序列化的单利

public class Singleton implements Serialzable{    private static Singleton instance =new Singleton();    private Singleton(){//破解反射        if(null!=instance){            throw new RunTimeException();        }    }    public static Singleton getInstance(){        return instance;    }    //破解反序列化,这个方法是如果已经有对象了,再调用的时候把原来的调回去,不用再给创建新的对象    private Object readResolve()throws ObjectStreamException{        return instance;    }}

相对环境测试效率

import java.util.concurrent.CountDownLatch;/** * 相对环境下多线程并发测试单利运行效率 * @author Administrator * */public class Test2 {    public static void main(String[] args) throws InterruptedException {        long start =System.currentTimeMillis();        int threadNum=10;        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);        for(int i=0;i<threadNum;i++){            new Thread(new Runnable(){                @Override                public void run() {                    for(int i=0;i<1000000;i++){                        Object o = Singleton.getInstance();                        //Object o =Singleton.INSTANCE;                     }                    countDownLatch.countDown();                }            }).start();        }        countDownLatch.await();        long end =System.currentTimeMillis();        System.out.println("总耗时:"+(end-start));    }}
0 0
原创粉丝点击