java 设计模式之单例模式

单例模式指的是在整个项目中只存在一个该类的实例化,全局公用这个类(即所有的请求都共享这个类)

单例模式的应用场景,比如数据库连接池,线程池(例如处理上传,整个项目限制上传的最大数为1000,则可以将处理上传的线程池设置为单例,队列长度为1000,超过1000提示,稍后上传),dao层的数据库封装类。

单例模式实现方式,饿汉模式(直接放在内存中,类在项目初始化的时候,被创建)和懒汉模式(类在第一次访问的时候,创建,多线程访问的时候存在,线程安全问题),利用类的加载机制,静态内部类(可以实现懒加载,并且线程安全),枚举实现(推荐)

1.饿汉模式

public class SinglePattern {

    public static  SinglePattern sp= new SinglePattern();
    
    private  SinglePattern(){}
    
    public static SinglePattern getInstance(){
        return sp;
    }

}

2.懒汉式

public class SinglePattern {

    public static  SinglePattern sp= null;
    
    private  SinglePattern(){}
    
    public static SinglePattern getInstance(){
        //存在线程安全,多线程访问会同时创建多个SinglePattern
        if(sp==null){
            sp = new SinglePattern();
        }
        
        return sp;
    }

}

2.1枷锁的懒汉式(双重校验,实现了懒加载,同时多线访问的时候,只有类没被实例化的时候去创建,synchronized 内置到方法里面,大大的提高程序的执行效率)

public class SinglePattern {

    public static  SinglePattern sp= null;
    
    private  SinglePattern(){}
    
    public static SinglePattern getInstance(){
        
        if(sp==null){
            synchronized (SinglePattern.class) {
                if(sp==null){
                    sp = new SinglePattern();
                }
            }
        }
        return sp;
    }
}

3.0类的加载机制(关键字ststaic,修饰代码块,类被加载的时候,静态代码块被执行)

public class SinglePattern {

    public static  SinglePattern sp= null;    
    private  SinglePattern(){}   
    static {
        sp = new SinglePattern();
    }  
    public static SinglePattern getInstance(){
        return sp;
    }
}

4.0静态内部类(静态内部类,懒加载并且线程安全的,与2,3相比从被动加载创建,改为了自己主动创建)

public class SinglePattern {

private static class GetSinglePattern{
        final static SinglePattern sp = new SinglePattern();
    }
 private  SinglePattern(){}
  public static SinglePattern getInstance(){
        return GetSinglePattern.sp;
    }

}

以上的4种方式实现单例模式,都是可以通过反射,(如果类实现了序列化接口)反序列化破解,从而创建多个。

反序列化解决办法如下可以在类里面添加

  private Object readResolve() {
            System.out.println("print from readResolve() method");
            return getInstance();
        }

        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
            System.out.println("print from readObject() method");
            ois.defaultReadObject();
        }

类级内部类:是指对象内部类有static 关键字修饰
对象级内部类:是指对象内部类没有static关键字修饰
 类级内部类,相当于外部对象的static 成员变量,与外部对象没有依赖关系的,类级内部类只能使用外部类的静态属性
  对象级内部类,依赖于外部对象,必须外部对象创建后,才能使用
 类级内部类相当于外部类的成员变量,只有在第一次使用的时候才会被加载

但是反射是会创建多个对象的

5.枚举类(懒加载,线程安全,并且可以防止反射,反序列化创建多个实例)

public enum EnumSinglePattern{    
        INSTANCE;        
        /**
         * 自己的业务逻辑    
         */
        public static void method() {
            
        }    
}

项目中如果不考虑资源加载,内存充足的情况可以使用第一种饿汉模式

项目中要实现懒加载,则可以考虑采用4静态内部类

项目中要考虑到单例的安全性和唯一性,使用第5,枚举类

servlet容器启动的时候,所有的java类会被加载到jvm里面,类只会被加载一次,通过new(),反射等方法可以创建多个实例,如果有多个类加载器,都加载了单例类,则单例类会被创建多次,一个加载器创建一次

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/3195939/blog/850009

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值