zoukankan      html  css  js  c++  java
  • 设计模式 单例模式的几种实现方式

    一 简介

    单例模式,对于一个类只有一个实例化对象。

    必要点:

     私有化 构造方法,不让new

     编写类方法 暴露单例对象

     私有化单例对象,只提供给内部使用

    二 考虑到并发条件下的情况下

    实现方式主要有如下四种

     第一种,饿汉模式随着类加载,而实例化。类只会实例化一次,所以不会有并发的问题

    /**
     * @program: test
     * @description: 单例  四种实现方式  第一饿汉式  类加载就初始化
     *                第二  懒汉式  方法加锁
     *                第三 双重效验
     *                第四 静态内部类
     * @author:
     * @create: 2019-07-09 19:46
     */
    public class Singleton {
        private Singleton() {
    
        }
    
        private static Singleton singleton = new Singleton();
    
        public static Singleton getSingleton() {
            return singleton;
        }
    
    }
    

      

    第二种 对方法封锁,保证临界资源安全,好处:想加载时,才加载

    public class Singleton1 {
        private static Singleton1 singleton1;
        private Singleton1() {
    
        }
    
        public synchronized static Singleton1 getSingleton() {
            if(singleton1==null)
                singleton1 = new Singleton1();  //只有第一次进入方法体的时候 创建对象
            return singleton1;
        }
    
    }
    

      对比的是一种,线程不安全的。

    /**
     * @program: test
     * @description: 不加限制的懒加载
     * @author:
     * @create: 2019-07-09 20:09
     */
    public class Singleton4 {
        private static Singleton4 singleton4;
    
        private Singleton4() {
    
        }
    
    
    
        public static Singleton4 getSingleton() {
            if (singleton4 == null) {
                singleton4 = new Singleton4();
            }
            return singleton4;
    
        }
    }
    

      第三种 方法:双检验

    public class Singleton3 {
    
        private static volatile Singleton3 singleton3;
    
        private Singleton3() {
    
        }
    
        public static Singleton3 getSingleton() {
            if (singleton3 == null) {
                synchronized (Singleton3.class) {
                    if (singleton3 == null) {
                        singleton3 = new Singleton3();
                    }
                }       //同样 保证第一次 进入方法体 进行初始化   优化第二种情况
            }
            return singleton3;
        }
    
    }
    

      第四种方法:利用内部类的特性,内部类可以访问外部类的变量;内部类同样也只会加载一次

    public class Singleton2 {
        private static Singleton2 singleton2;
    
        private Singleton2() {
    
        }
    
        private static class SingletonPv {
            private static Singleton2 singleton2 = new Singleton2();
        }
    
        private Singleton2 getSingleton() {
            return SingletonPv.singleton2;
        }
    }
    

      

    最后是测试,让100个线程 同时去获取单例对象,四种方法 都没问题;而没加并发限制,很容易出现100个线程获得的对象不相同的情况

    public class Main {
        public static void main(String[] args) {
            final CountDownLatch countDownLatch = new CountDownLatch(100);
            for (int i = 0; i < 100; i++) {
                Thread thread = new Thread(new Runnable() {
                    public void run() {
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println( Singleton3.getSingleton()+Thread.currentThread().getName());
                    }
                });
                thread.start();
                countDownLatch.countDown();
    
            }
        }
    }
    

      

  • 相关阅读:
    AngularJS之页面跳转Route
    ajax上传图片的本质
    JQuery-基础学习1
    Java跨域问题的处理详解
    红黑树
    查找算法
    八大排序算法
    linux下安装nginx
    libevent 和 libev 提高网络应用性能
    Linux下libevent安装与示例
  • 原文地址:https://www.cnblogs.com/caijiwdq/p/11160895.html
Copyright © 2011-2022 走看看