zoukankan      html  css  js  c++  java
  • JAVA实现单例模式

    JAVA实现单例模式主要有:懒汉、饿汉、双重检验锁、静态内部类和枚举几种方式。

    一、懒汉,线程不安全

    public class Singleton {
        private static Singleton instance;
        private Singleton (){}
        public static Singleton getInstance() {
         if (instance == null) {
             instance = new Singleton();
         }
         return instance;
        }
    }
    

     这种方式之所以线程不安全是因为当多个线程同时使用getInstance()方法时,可能产生多个实例。

    二、懒汉,线程安全

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    加上synchronized关键字后,保证了线程安全,但是任何时候只能有一个线程调用getInstance()方法,所以并不高效。

    三、饿汉

    public class Singleton{
        //类加载时就初始化
        private static final Singleton instance = new Singleton();
        
        private Singleton(){}
        public static Singleton getInstance(){
            return instance;
        }
    }
    

     这种方式使得类在装载时就创建了实例。

    四、双重检验锁

    public class Singleton {
        private volatile static Singleton instance; //声明成 volatile
        private Singleton (){}
        public static Singleton getSingleton() {
            if (instance == null) {                         
                synchronized (Singleton.class) {
                    if (instance == null) {       
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
       
    }
    

     这里有两点要注意,一是两次检验instance==null,因为可能有多个线程同时进入外面的if,如果没有内部if检查,会创建多个实例。二是volatile关键字。因为instance=new Singleton()分三步进行:

    1) 给instance分配内存;

    2)调用Singleton构造函数初始化成员变量;

    3)将instance对象指向内存空间。

    由于JVM编译器中存在指令排序的优化,也就是说2)和3)的顺序是不能保证的。设想一下,如果执行顺序是1,3,2,在执行完3之后,然后被线程二占用,这时instance已经是非null,线程二直接返回instance,这样在使用时就会报错。

    volatile的作用在于禁止指令重排序优化。

    五、静态内部类

    public class Singleton {  
        private static class SingletonHolder {  
            private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
            return SingletonHolder.INSTANCE; 
        }  
    }
    

     这也是一种”懒汉”的方式,把实例化推迟到使用getInstance()方法之后。

    六、枚举

    public enum EasySingleton{
        INSTANCE;
    }
    

     可见枚举类型是最简单的一种方法。

  • 相关阅读:
    Python学习---IO的异步[tornado模块]
    Python学习---IO的异步[twisted模块]
    Python学习---IO的异步[gevent+Grequests模块]
    Python学习---IO的异步[asyncio +aiohttp模块]
    Python学习---IO的异步[asyncio模块(no-http)]
    Python学习---Python的异步IO[all]
    Python学习---爬虫学习[scrapy框架初识]
    Python学习---Django关于POST的请求解析源码分析
    Python学习---爬虫学习[requests模块]180411
    Python实例---CRM管理系统分析180331
  • 原文地址:https://www.cnblogs.com/lumouren009/p/4255880.html
Copyright © 2011-2022 走看看