• 单例模式


          设计模式大家都很熟悉,今天来记录下最基础也最简单的单例模式

          单例模式分为两类,一是饿汉式,另外就是相对的懒汉式

          想来看看饿汉式

          常见的实现方式如下:

     1 public class SingletonHungry {
     2     private static SingletonHungry instance = new SingletonHungry();
     3 
     4     private String token;
     5 
     6     private SingletonHungry() {
     7         token = System.currentTimeMillis() + "";
     8     }
     9 
    10     public static SingletonHungry getInstance() {
    11         return instance;
    12     }
    13 
    14     public String getToken() {
    15         return token;
    16     }
    17 }

    新增token来验证线程安全

    来个线程安全的

    public class SingletonHungrySafe {
    
        private static String token;
    
        //jvm加载时会实例化
        private static class Holder {
            private static SingletonHungrySafe INSTANCE = new SingletonHungrySafe();
        }
    
        private SingletonHungrySafe() {
            token = System.currentTimeMillis() + "";
        }
    
        public static final SingletonHungrySafe getInstance() {
            return Holder.INSTANCE;
        }
    
        public String getToken() {
            return token;
        }
    }
    可以保证在各个线程获取Holder.INSTANCE变量之前完成。在保证线程安全的同时,又可以延迟实例化,并且没有降低并发性

    接下来看看懒汉式,相对的,懒汉式是用时才加载,延后性。
    先来个线程不安全的
    public class SingletonLazy {
        private static SingletonLazy instance;
    
        private SingletonLazy() {
        }
    
        public static SingletonLazy getInstance() {
            if (instance == null) {
                instance = new SingletonLazy();
            }
            return instance;
        }
    }

    线程安全的

    public class SingletonLazySafe {
        private volatile static SingletonLazySafe instance;
    
        private SingletonLazySafe() {
        }
    
        public static SingletonLazySafe getInstance() {
            if (null == instance) {
                synchronized (SingletonLazySafe.class) {
                    if (null == instance) {
                        instance = new SingletonLazySafe();
                    }
                }
            }
            return instance;
        }
    }
    双重检查加锁,保证线程安全。

    同时,我们可以对这些进行测试
    public class SingletonTest {
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 1000; i++) {
                Single single = new Single();
                single.start();
            }
        }
    
        static class Single extends Thread {
    
            @Override
            public void run() {
                checkSingleHungry();
            }
        }
    
        private static void checkSingleHungrySafe() {
            SingletonHungrySafe singletonHungrySafe = SingletonHungrySafe.getInstance();
            System.out.println("Thread id=" + Thread.currentThread().getId() + "token:" + singletonHungrySafe.getToken());
        }
    
        private static void checkSingleHungry() {
            SingletonHungry singletonHungry = SingletonHungry.getInstance();
            System.out.println("Thread id=" + Thread.currentThread().getId() + "token:" + singletonHungry.getToken());
        }
    }

    验证线程安全问题

          

  • 相关阅读:
    LINQ分组排序后获取每组第一条记录
    String 中的Trim
    C# Switch优雅写法
    C# 输入指定日期获取当前年的第一天 、当前年的最后天、某月的第一天 、某月的最后一天
    快捷方式 ABP——切换MySQL数据库
    新建立git分支,之后将分支合并到master上
    C# Contains()、 == 和Equals() 比较
    使用TimeSpan 日期与时间拼接
    ActiveReports报表行号
    iOS基础(八)——最新更新方法,每天只提示一次
  • 原文地址:https://www.cnblogs.com/xzshare/p/12239942.html
Copyright © 2020-2023  润新知