01_java设计模式之单例模式

java设计模式之单例模式

一.应用场景

在实际开发中,当我们要求一个类只能被实例化一次时,比如各种各样的Manager、各种各样的Factory,可以使用单例模式

二.构造单例的常规步骤

  • 提供一个private static final 的当前类的实例变量INSTANCE
  • 将构造方法设置为private,保证其对外不能通过new关键字实例化
  • 通过getInstance的静态方法返回一个唯一的当前类的实例

三.单例的七种写法

  1. 饿汉模式

    public class SingleInstance01 {
    
        private static final SingleInstance01 INSTANCE = new SingleInstance01();
    
        private SingleInstance01() {}
    
        public static SingleInstance01 getInstance() {
            return INSTANCE;
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            SingleInstance01 s1 = SingleInstance01.getInstance();
            SingleInstance01 s2 = SingleInstance01.getInstance();
            System.out.println(s1 == s2);//输出true
        }
    
    }
    

    类加载到内存后,就会创建一个实例对象
    由JVM保证线程安全
    JVM保证每一个class只会被load到内存一次,static的变量是在class被load到内存之后,会马上进行实例化,所以也保证了INSTANCE只会被初始化一次
    缺点是:不管用到与否,类加载时就会完成实例化

  2. 懒汉模式

    public class SingleInstance02 {
    
        private static SingleInstance02 INSTANCE;
        
        private SingleInstance02() {}
    
        public static SingleInstance02 getInstance() {
    
            if(INSTANCE == null) {
                doSomeThings();
                INSTANCE = new SingleInstance02();
            }
    
            return INSTANCE;
    
        }
        
        private static void doSomeThings() {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance02.getInstance().toString());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     com.gale.designpattern.singleinstance.SingleInstance02@3a2cad68
     com.gale.designpattern.singleinstance.SingleInstance02@48ac2be5
     com.gale.designpattern.singleinstance.SingleInstance02@48ac2be5
     com.gale.designpattern.singleinstance.SingleInstance02@4e35792a
     com.gale.designpattern.singleinstance.SingleInstance02@2cb30bd3
     com.gale.designpattern.singleinstance.SingleInstance02@11d32fc4
     com.gale.designpattern.singleinstance.SingleInstance02@d084795
     com.gale.designpattern.singleinstance.SingleInstance02@48ac2be5
     com.gale.designpattern.singleinstance.SingleInstance02@48ac2be5
     com.gale.designpattern.singleinstance.SingleInstance02@48ac2be5
     ******************************************************************/
    

    虽然达到了按需初始化的目的,却带来了线程不安全的问题

    在这里插入图片描述

  3. 在懒汉模式的基础上,通过synchronized锁定类的class对象解决线程不安全的问题,也叫做线程安全的懒汉模式,但也带来了效率上的下降

    public class SingleInstance03 {
    
        private static SingleInstance03 INSTANCE;
    
        private SingleInstance03() {}
    
        public static synchronized SingleInstance03 getInstance() {
    
            if(INSTANCE == null) {
    
                doSomeThings();
    
                INSTANCE = new SingleInstance03();
            }
    
            return INSTANCE;
    
        }
    
        private static void doSomeThings() {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance03.getInstance().toString());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     com.gale.designpattern.singleinstance.SingleInstance03@1469c295
     ******************************************************************/
    
  4. 试图通过减小同步代码块的方式来提高效率,不可行

    public class SingleInstance04 {
    
        private static SingleInstance04 INSTANCE;
    
        private SingleInstance04() {}
    
        public static SingleInstance04 getInstance() {
    
            if(INSTANCE == null) {
                synchronized (SingleInstance04.class) {
                    doSomeThings();
                    INSTANCE = new SingleInstance04();
                }
            }
    
            return INSTANCE;
    
        }
    
        private static void doSomeThings() {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance04.getInstance().toString());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     com.gale.designpattern.singleinstance.SingleInstance04@1ca5fe10
     com.gale.designpattern.singleinstance.SingleInstance04@1ca5fe10
     com.gale.designpattern.singleinstance.SingleInstance04@1ca5fe10
     com.gale.designpattern.singleinstance.SingleInstance04@1ca5fe10
     com.gale.designpattern.singleinstance.SingleInstance04@21b39199
     com.gale.designpattern.singleinstance.SingleInstance04@6fd8b67a
     com.gale.designpattern.singleinstance.SingleInstance04@b6f008f
     com.gale.designpattern.singleinstance.SingleInstance04@18f3035c
     com.gale.designpattern.singleinstance.SingleInstance04@8fddaf1
     com.gale.designpattern.singleinstance.SingleInstance04@1dce2a4
     ******************************************************************/
    

    在这里插入图片描述

  5. 双重检查的synchronized单例写法

    public class SingleInstance05 {
    
        private static SingleInstance05 INSTANCE;
    
        private SingleInstance05() {}
    
        public static SingleInstance05 getInstance() {
    
            if(INSTANCE == null) {
                synchronized (SingleInstance05.class) {
                    if(INSTANCE == null) {
                        doSomeThings();
                        INSTANCE = new SingleInstance05();
                    }
                }
            }
    
            return INSTANCE;
    
        }
    
        private static void doSomeThings() {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance05.getInstance().toString());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     com.gale.designpattern.singleinstance.SingleInstance05@7dcec037
     ******************************************************************/
    
  6. 静态内部类的单例写法(最完美的写法之一)

    public class SingleInstance06 {
    
        private SingleInstance06() {
        }
    
        private static class SingleInstance06Holder {
            private static final SingleInstance06 INSTANCE = new SingleInstance06();
        }
    
        public static SingleInstance06 getInstance() {
            return SingleInstance06Holder. INSTANCE;
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance06.getInstance().toString());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     com.gale.designpattern.singleinstance.SingleInstance06@418b0eca
     ******************************************************************/
    

    由JVM保证单例和线程安全
    加载外部类时不会加载内部类,而是在getInstance方法被调用时,内部类才会被加载,这样就实现了懒加载

  7. 枚举单例:不仅可以解决线程同步,还可以防止反序列化(因为枚举类没有构造方法,即使反序列化后,也不能被实例化)(最完美的写法之一)

    public enum SingleInstance07 {
    
        INSTANCE;
    
        public  static SingleInstance07 getInstance() {
            return INSTANCE;
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(SingleInstance07.getInstance().hashCode());
                    }
                }).start();
            }
        }
    
    }
    /*************************** 输出结果 *******************************
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     1467106563
     ******************************************************************/
    
发布了79 篇原创文章 · 获赞 45 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gzx110304/article/details/104766027
今日推荐