Java单例模式 注意的问题

时间:2015-03-15 19:34:52   收藏:0   阅读:161

问题1.效率问题:如果不需要用到单例类的对象,如何保证单例类对象不会被创建;

问题2.线程安全:如何保证获取到的对象是单例的。

 

1. 一般单例类的写法有:

class Singleton
{
    private static Singleton instance = null;

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

注:这么写仅在单线程中保证单个实例

2. 可以加同步解决以线程安全问题,但是效率相对较低

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

 3.其实也有另外的写法:

class Singleton
{
    private static Singleton instance = new Singleton();
    
    private Singleton()
    {
    }
    
    public static Singleton getInstance()
    {
        return instance;
    }
    
    public static int i = 3;
    
    public static void test()
    {
        System.out.println("test invoked.");
    }
}

注:这样解决了同步的问题,但是当静态test()方法被调用或者静态变量i被调用,即使你不需要使用单例对象,他也已经被加载到了内存中了

 4.推荐的写法如下:使用内部类方式,JVM保证在使用到内部类时才去初始化其成员变量,并保证线程安全。

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

 

补充: 

 java类加载过程:类什么时候会初始化。

一个java文件从被加载到被卸载这个生命过程,总共要经历四个阶段:

加载->链接(验证+准备+解析)->初始化(使用前的准备)->使用->卸载

什么时候要对类进行初始化工作, jvm有严格的规定(四种情况):

1.遇到new,getstatic,putstatic,invokestatic这4条字节码指令时,加入类还没进行初始化,则马上对其进行初始化工作。其实就是3种情况:用new实例化一个类时、读取或者设置类的静态字段时(不包括被final修饰的静态字段,因为他们在类编译的时候已经被塞进常量池了)、以及执行静态方法的时候

2.使用java.lang.reflect.*的方法对类进行反射调用的时候,如果类还没有进行过初始化,马上对其进行。

3.初始化一个类的时候,如果他的父亲还没有被初始化,则先去初始化其父亲。

4.当jvm启动时,用户需要指定一个要执行的主类(包含static void main(String[] args)的那个类),则jvm会先去初始化这个类。

以上4种预处理称为对一个类进行主动的引用,其余的其他情况,称为被动引用,都不会触发类的初始化。

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!