码迷,mamicode.com
首页 > 编程语言 > 详细

Java设计模式の单例模式

时间:2017-05-12 01:42:55      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:--   ==   反射   html   资料   for   ilo   避免   target   

--------------------------------------------------

目录

  1.定义

  2.常见的集中单例实现

    a.饿汉式,线程安全 但效率比较低

    b.单例模式的实现:饱汉式,非线程安全

    c.饱汉式,线程安全简单实现

    d.线程安全 并且效率高  单例模式最优方案

  3.总结

    a.使用枚举的单例模式

    b.使用枚举,static处调用,初始化一次

--------------------------------------------------

 

1.定义

确保一个类只有一个实例,并提供一个全局访问点!

2.常见的集中单例实现

  a.饿汉式,线程安全 但效率比较低

/** 
 * 单例模式的实现:饿汉式,线程安全 但效率比较低 
 */  
public class SingletonTest {  

    // 定义一个私有的构造方法
    private SingletonTest() {  
    }  

    // 将自身的实例对象设置为一个属性,并加上Static和final修饰符
    private static final SingletonTest instance = new SingletonTest();  

    // 静态方法返回该类的实例
    public static SingletonTest getInstancei() {  
        return instance;  
    }  
  
}

  b.单例模式的实现:饱汉式,非线程安全   

/**  
 * 单例模式的实现:饱汉式,非线程安全   
 *   
 */  
public class SingletonTest {

    // 定义私有构造方法(防止通过 new SingletonTest()去实例化)
    private SingletonTest() {   
    }   

    // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
    private static SingletonTest instance;   

    // 定义一个静态的方法(调用时再初始化SingletonTest,但是多线程访问时,可能造成重复初始化问题)
    public static SingletonTest getInstance() {   
        if (instance == null)   
            instance = new SingletonTest();   
        return instance;   
    }   
} 

  c.饱汉式,线程安全简单实现  

/**  
 * 单例模式的实现:饱汉式,线程安全简单实现   
 *   
 */  
public class SingletonTest {

    // 定义私有构造方法(防止通过 new SingletonTest()去实例化)
    private SingletonTest() {   
    }   

    // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
    private static SingletonTest instance;   

    // 定义一个静态的方法(调用时再初始化SingletonTest,使用synchronized 避免多线程访问时,可能造成重的复初始化问题)
    public static synchronized  SingletonTest getInstance() {   
        if (instance == null)   
            instance = new SingletonTest();   
        return instance;   
    }   
} 

  d.线程安全 并且效率高  单例模式最优方案

/**  
 * 单例模式最优方案
 * 线程安全  并且效率高  
 *  
 */  
public class SingletonTest { 

    // 定义一个私有构造方法
    private SingletonTest() { 
     
    }   
    //定义一个静态私有变量(不初始化,不使用final关键字,使用volatile保证了多线程访问时instance变量的可见性,避免了instance初始化时其他变量属性还没赋值完时,被另外线程调用)
    private static volatile SingletonTest instance;  

    //定义一个共有的静态方法,返回该类型实例
    public static SingletonTest getIstance() { 
        // 对象实例化时与否判断(不使用同步代码块,instance不等于null时,直接返回对象,提高运行效率)
        if (instance == null) {
            //同步代码块(对象未初始化时,使用同步代码块,保证多线程访问时对象在第一次创建后,不再重复被创建)
            synchronized (SingletonTest.class) {
                //未初始化,则初始instance变量
                if (instance == null) {
                    instance = new SingletonTest();   
                }   
            }   
        }   
        return instance;   
    }   
}

 

3.总结

  

  【以上单例模式】传统的两私有一公开(私有构造方法、私有静态实例(懒实例化/直接实例化)、公开的静态获取方法)涉及线程安全问题(即使有多重检查锁也可以通过反射破坏单例)

目前最为安全的实现单例的方法是通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。如下

  a.使用枚举的单例模式

 

/**
 * 使用枚举的单例模式
 *
 * @author yzl
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class EnumSingleton{
    private EnumSingleton(){}
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
    
    private static enum Singleton{
        INSTANCE;
        
        private EnumSingleton singleton;
        //JVM会保证此方法绝对只调用一次
        private Singleton(){
            singleton = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return singleton;
        }
    }
}

  b.使用枚举,static处调用,初始化一次

import java.util.ArrayList;
import java.util.List;

/**
 * 初始化的优雅实现
 * 可以在static处调用,
 * 也可以在普通方法里调用,都保证只初始化一次
 * 
 * 当然将enum块的代码直接放到StaticInitTest类的private static 方法里做也是可以的
 *
 * @author yzl
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class StaticInitTest {
    private static List<Integer> dataList = null;
    
    static{
        dataList = Singleton.INSTANCE.init();
    }
    
    /**
     * 
     * 单例模式来填充数据
     *
     * @author yzl
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    private static enum Singleton {
        INSTANCE;
        private List<Integer> list;
        
        private Singleton(){
            fillData();
        }
        /**
         * 
         * 初始化数据
         *
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
        private void fillData(){
            list = new ArrayList<Integer>(5);
            for(int i =1; i<6; i++){
                list.add(i);
            }
        }

        /**
         * 
         * 初始化的入口
         *
         * @see [相关类/方法](可选)
         * @since [产品/模块版本](可选)
         */
        public List<Integer> init(){
            return list;
        }
    }
}

 

参考资料:java单例之enum实现方式

 

     java设计模式--单例模式

Java设计模式の单例模式

标签:--   ==   反射   html   资料   for   ilo   避免   target   

原文地址:http://www.cnblogs.com/KongkOngL/p/6843447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!