设计模式第八讲-单例模式

1.基本介绍

1.1定义与类型

定义:保证一个类仅有一个实例,并提供一个全局访问点
类型:创建型

1.2 单例-适用场景

想确保任何情况下都绝对只有一个实例
单服务-计数器 线程池-设计 -链接池

1.3 优点和缺点

在内存中只有一个实例,减少内存开销
可以避免资源的多重占用
严格控制访问
缺点:
没有接口,扩展困难

1.4 多线程debug

在这里插入图片描述
all:本线程的断点
thread:控制线程执行的顺序,会一直等待来处理它。
makedefault:

1.5 懒汉式实现和多线程问题处理

懒汉式实现的会出现多线程问题

/**
 * 懒汉式
 * 1.静态的单例对象
 * 2.构造函数私有化
 * 3.懒汉式延迟加载,需要使用的时候才加载
 */
public class LazySingleton {
    private static LazySingleton lazySingleton=null;
    private LazySingleton(){

    }
    /**
     * 线程不安全,多线程读时候,第一个线程
     * @return
     */
    public static LazySingleton getInstance(){
        if(lazySingleton==null){
            lazySingleton=new LazySingleton();
        }
        return lazySingleton;
    }
   
}
public class T  implements Runnable{
    public void run() {
        LazySingleton lazySingleton=LazySingleton.getInstance();

        System.out.println(Thread.currentThread().getName()+"--"+lazySingleton);
    }
}
public class Test {

    public static void main(String[] args) {
     //   LazySingleton lazySingleton=LazySingleton.getInstance();
        Thread t1=new Thread(new T());
        Thread t2=new Thread(new T());
        t1.start();
        t2.start();
        //多线程debug
        System.out.println();
    }
}

在这里插入图片描述
对于上面在上面的多线程的问题处理:
1.加锁在方法上。同步方法。类的class文件。锁了这个类。性能消耗大

 /**
     * 线程不安全,多线程读时候,第一个线程
     * @return
     */
    public synchronized static LazySingleton getInstance(){
        if(lazySingleton==null){
            lazySingleton=new LazySingleton();
        }
        return lazySingleton;
    }

2.double check

public class T  implements Runnable{
    public void run() {
       // LazySingleton lazySingleton=LazySingleton.getInstance();
        LazyDoubleCheckSingleton lazyDoubleCheckSingleton=LazyDoubleCheckSingleton.getInstance();
        System.out.println(Thread.currentThread().getName()+"--"+lazyDoubleCheckSingleton);
    }
}
public class LazyDoubleCheckSingleton {
//volatile 防止重排序
    private volatile static LazyDoubleCheckSingleton lazySingleton=null;
    private LazyDoubleCheckSingleton (){

    }

    /**
     * 线程不安全,多线程读时候,第一个线程
     * @return
     */
    public  static LazyDoubleCheckSingleton  getInstance(){
        if(lazySingleton==null){
            synchronized (LazyDoubleCheckSingleton.class){
              if(lazySingleton==null){
                  lazySingleton=new LazyDoubleCheckSingleton();
                  //1.分配内存给这个对象
                  //2.初始化对象
                  //存在指令重排序。
                  //3.设置lazyDoubleCheckSigleton 指向内存地址
              }
            }

        }
        return lazySingleton;
    }
}

1.6 饿汉式:

/**
 * 饿汉式,类加载就完成初始化,线程没有同步问题。
 */
public class HungrySingleton {
    private final static  HungrySingleton hungrySingleton;
    static {
        hungrySingleton=new HungrySingleton();
    }
    private HungrySingleton(){
    
    }
    public static HungrySingleton getInstance(){
       return hungrySingleton;
    }
}

1.7 序列化和反序列化破坏单例

/**
 * 饿汉式,类加载就完成初始化,线程没有同步问题。
 */
public class HungrySingleton implements Serializable {
    private final static  HungrySingleton hungrySingleton;
    static {
        hungrySingleton=new HungrySingleton();
    }
    private HungrySingleton(){

    }
    public static HungrySingleton getInstance(){
       return hungrySingleton;
    }
    private Object readResolve(){
        return hungrySingleton;
    }
}
public class Test {
   public static void main(String[] args) throws Exception {
     HungrySingleton instance = HungrySingleton.getInstance();
       ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("singletonfile"));
      oos.writeObject(instance);
        File file=new File("singletonfile");
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
        HungrySingleton newInstance= (HungrySingleton) ois.readObject();
        System.out.println(instance==newInstance);
  }
}

2.JDK 源码实战

Runtime

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

3.总结与思考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据学习爱好者

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值