`
chenhua_1984
  • 浏览: 1251237 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

java关于单例模式的一些疑问?

阅读更多

    小弟最近想学习java的设计模式,就从单例模式来学起吧。大家知道在java语言中,可以利用static 关键字来构建单例模式,主要是因为static 这个关键字在所在的类在被java虚拟机装载的时候,变量是最先被装载(如果有多个,那么按照从上往下的顺序执行的),并且是全局共享的。

    因此:按照这个理解:我写了一个单例模式。代码如下:

    public class Test{
    private static Test test=null;
    public static Test getInstence(){

                 if(test==null)
                {
                     test=mew Test();
                }
                  return test;

      }
   }

       在这个方法里,我申明了一个private static类型的成员变量,然后申明了一个static类型的方法,判断test如果是null,则实例化,然后返回Test类的一个实例。应为static类型的变量是全局共享的,所以,一旦test被实例化,那么则被存放到java虚拟机的堆中,全局共享,以后不会在实例化。直到类的生命周期结束然后才会被销毁。在别的类要引用的时候,只需要Test.getInstence()就可以获得一个实例。这就是我理解的单利模式。

 

    但我在网上看了另一种写法,说要有一个私有的构造函数,代码是这样的。

  
  public class Test{
      private Test(){}

      private static Test test=new Test();

      public static Test getInstence(){ 
  
         return test;
      

       }
  }

我是这样理解这个类的:

 1    private static Test test=new Test();在jvm 装载这个类的时候会初始化这个声明,Test类的实例test已经被实例化。并且全局共享。

 2     public static Test getInstence(){ 
  
         return test;
      

       }

  static的方法getInstence用来返回Test 类的实例。这个实例就是上面已经实例化的那个(唯一的一个)

 问题一:问题是私有的构造函数,我不明白为什么一定要有个私有的构造函数?大家帮  忙看看!

 问题二:在开发单例模式中有那些是需要注意的地方?比如构造方法之类的要注意什 么?

 问题三:单利模式有几种形式?能不能给个例子?听说有懒汉式什么的?

问题四:什么时候需要用到单例模式?

      请大家不宁赐教!多谢!我的邮箱lifeneedyou@163.com ,可以发邮件给我!

 

 

分享到:
评论
39 楼 chenhua_1984 2009-04-27  
lkjust08 写道
一般Singleton模式通常有几种形式:

public class Singleton {

  private Singleton(){}

  //在自己内部定义自己一个实例,是不是很奇怪?
  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  
  public static Singleton getInstance() {
    return instance;   
   }
}




第二种形式:

public class Singleton {
  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  if (instance==null)
    instance=new Singleton();
  return instance;   }

}




使用Singleton.getInstance()可以访问单态类。

上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。

一般认为第一种形式要更加安全些。



多谢!明白了
38 楼 lkjust08 2009-04-27  
一般Singleton模式通常有几种形式:

public class Singleton {

  private Singleton(){}

  //在自己内部定义自己一个实例,是不是很奇怪?
  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  
  public static Singleton getInstance() {
    return instance;   
   }
}




第二种形式:

public class Singleton {
  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  if (instance==null)
    instance=new Singleton();
  return instance;   }

}




使用Singleton.getInstance()可以访问单态类。

上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。

一般认为第一种形式要更加安全些。


37 楼 sunnymoon 2009-04-25  
kulinglei 写道
sunnymoon 写道
longrui 写道
chenhua_1984 写道
1构造函数有什么样的要求?
2这里的线程安全问题是怎么回事?

1.私有构造行数是禁止通过实例该类获得对象,如:
new Test().getInstence();

2.线程安全是指如果有多个线程,在第一个线程还没有执行到new Test()的时候,第二个线程调用该方法时判断test仍然为null,所以仍然会执行new Test()。
所以一般使用synchronized关键字将该方法声明成同步方法,如:
public static synchronized Test getInstence


线程安全是指多个线程访问一个资源时(这里指对象),不会发生冲突,保证同一时间只有一个线程访问该资源。
单例中的类只实例化一次,new Test()不会多次执行,每次线程访问时得到同一个实例。这里说的有点问题。


多个线程同时操作一个单例,不就不安全了吗???


no
36 楼 kulinglei 2009-04-24  
youthon 写道
有人根据创建的时间把单例模式分为懒汉式和饿汉式
懒汉式是指在调用的时候才创建,就像你前面的代码所做的,优点是只有用到了才会占用资源
饿汉式是在初始化就创建了这个对象,优点是预先加载,在调用时省去了创建(还有可能加载配置数据)的时间

饿汉式:在类加载时static{}.静态块中
35 楼 youthon 2009-04-24  
有人根据创建的时间把单例模式分为懒汉式和饿汉式
懒汉式是指在调用的时候才创建,就像你前面的代码所做的,优点是只有用到了才会占用资源
饿汉式是在初始化就创建了这个对象,优点是预先加载,在调用时省去了创建(还有可能加载配置数据)的时间
34 楼 kulinglei 2009-04-24  
sunnymoon 写道
longrui 写道
chenhua_1984 写道
1构造函数有什么样的要求?
2这里的线程安全问题是怎么回事?

1.私有构造行数是禁止通过实例该类获得对象,如:
new Test().getInstence();

2.线程安全是指如果有多个线程,在第一个线程还没有执行到new Test()的时候,第二个线程调用该方法时判断test仍然为null,所以仍然会执行new Test()。
所以一般使用synchronized关键字将该方法声明成同步方法,如:
public static synchronized Test getInstence


线程安全是指多个线程访问一个资源时(这里指对象),不会发生冲突,保证同一时间只有一个线程访问该资源。
单例中的类只实例化一次,new Test()不会多次执行,每次线程访问时得到同一个实例。这里说的有点问题。


多个线程同时操作一个单例,不就不安全了吗???
33 楼 sunnymoon 2009-04-24  
longrui 写道
chenhua_1984 写道
1构造函数有什么样的要求?
2这里的线程安全问题是怎么回事?

1.私有构造行数是禁止通过实例该类获得对象,如:
new Test().getInstence();

2.线程安全是指如果有多个线程,在第一个线程还没有执行到new Test()的时候,第二个线程调用该方法时判断test仍然为null,所以仍然会执行new Test()。
所以一般使用synchronized关键字将该方法声明成同步方法,如:
public static synchronized Test getInstence


线程安全是指多个线程访问一个资源时(这里指对象),不会发生冲突,保证同一时间只有一个线程访问该资源。
单例中的类只实例化一次,new Test()不会多次执行,每次线程访问时得到同一个实例。这里说的有点问题。

32 楼 kulinglei 2009-04-23  
构造方法私,是防止在其他类中new对象,但你的属性是static的,所以即使在其他类中new了n个对象,但他们的属性是共享的,所以要考虑安全问题,你可以加个类锁,这样数据就安全了,所以私有的构造方法不是必须的,
31 楼 C_J 2009-04-22  
引用
单例首要的条件就是线程安全,所以不会有线程公享资源的事情,何来资源一说?要是有资源公享的话,那还是单例吗?


是的,但我的理解“共享”是“所有线程共享了进程的资源”,而这里的单例实例就是其中的一部分。

  而“共享”并非“同时使用”吧~ 就像那位兄台说的“厕所”
  所以为了解决“同时使用”带来的问题,就得做好“线程安全”了。
30 楼 jansel 2009-04-22  
C_J 写道
tangshd 写道
本来不想注册 写道
Constructor的用法 和 static 的用法,如果不熟悉,可以用单例模式来加深对他们的理解。

单例模式的写法有很多吧,最简洁的才是最好的。

一个实例,虽然节约资源,缺点应该也很明显。就好比,厕所小便槽就一个,大家要排队等候。



兄台,您这个比喻好像不对吧..单例又不是单线程!


所有线程都共享一个资源

一个线程共享所有资源


要是“资源”是马桶,排队的就是“线程”。

兄台为什么认为那位兄台比喻不对呢??


单例首要的条件就是线程安全,所以不会有线程公享资源的事情,何来资源一说?要是有资源公享的话,那还是单例吗?
29 楼 C_J 2009-04-22  
tangshd 写道
本来不想注册 写道
Constructor的用法 和 static 的用法,如果不熟悉,可以用单例模式来加深对他们的理解。

单例模式的写法有很多吧,最简洁的才是最好的。

一个实例,虽然节约资源,缺点应该也很明显。就好比,厕所小便槽就一个,大家要排队等候。



兄台,您这个比喻好像不对吧..单例又不是单线程!


所有线程都共享一个资源

一个线程共享所有资源


要是“资源”是马桶,排队的就是“线程”。

兄台为什么认为那位兄台比喻不对呢??
28 楼 tangshd 2009-04-21  
本来不想注册 写道
Constructor的用法 和 static 的用法,如果不熟悉,可以用单例模式来加深对他们的理解。

单例模式的写法有很多吧,最简洁的才是最好的。

一个实例,虽然节约资源,缺点应该也很明显。就好比,厕所小便槽就一个,大家要排队等候。



兄台,您这个比喻好像不对吧..单例又不是单线程!
27 楼 akiraray 2009-04-18  
lucane 写道
看过这个一点点
Double-checked locking and the Singleton pattern
不过还是有点不明白

Out-of-order writes那段中

引用
public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;
}


3.Thread 1 proceeds to //3 and makes instance non-null, but before the constructor executes.

In my opinion,the instance should be null before the constructor executes.

I'm confused about that.

Thanks

双重check的好处就是

如果只是像平时一样 每次判断都要先进性同步操作 性能会降低
因为线程不安全的场景 只是在 第一次创建的时候发生

而double check
先判断是否 已经实例化了 如果实例化了直接跳过同步部分
如果没有实例化 那么就做一次同步--判断--初始化的动作
两者的差距其实就那行没有同步锁的判断,这样再实例化以后所有的getIntanse就不必都要走 同步锁--判断--解锁的这个很浪费性能的流程而已- -
26 楼 iaimstar 2009-04-17  
lucane 写道
看过这个一点点

3.Thread 1 proceeds to //3 and makes instance non-null, but before the constructor executes.

In my opinion,the instance should be null before the constructor executes.

I'm confused about that.

Thanks


先获得实例目的就是不做同步的额外处理,你不能保证取得对象实例的时候没有并发,这样会产生多个实例,而不是单例了,所以使用才生成需要同步,会增加额外的工作
提前获得实例的好处就是把实例化的工作交给系统来干,能保证不需要同步也能保证单例的成功
25 楼 tianlihu 2009-04-17  
一般认为在初始化时就指定好值是比较安全的,不能用时再初始化,虽然加上同步可以解决这个问题,但带来了额外的系统开销,不是好的解决方案
24 楼 lucane 2009-04-16  
看过这个一点点
Double-checked locking and the Singleton pattern
不过还是有点不明白

Out-of-order writes那段中

引用
public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {  //1
      if (instance == null)          //2
        instance = new Singleton();  //3
    }
  }
  return instance;
}


3.Thread 1 proceeds to //3 and makes instance non-null, but before the constructor executes.

In my opinion,the instance should be null before the constructor executes.

I'm confused about that.

Thanks
23 楼 本来不想注册 2009-04-16  
Constructor的用法 和 static 的用法,如果不熟悉,可以用单例模式来加深对他们的理解。

单例模式的写法有很多吧,最简洁的才是最好的。

一个实例,虽然节约资源,缺点应该也很明显。就好比,厕所小便槽就一个,大家要排队等候。

22 楼 C_J 2009-04-14  

“2.采用Holder类,是为了得用jdk对static变量的定义来保证多线程安全。”

没明白用这里的private Holder类能保证线程安全,莫非不这样做JDK就不去控制线程安全了么?

21 楼 chenhua_1984 2009-04-14  
rrsy23 写道
单例 有没有想过用静态方法会怎么样?

用静态方法就是把方法声明成类的静态方法!在jvm装载这个类的时候会先转载它,并且全局共享。用类名.方法名()来访问。不知道你这么说是什么用意?或则你是怎么想的?
20 楼 rrsy23 2009-04-13  
单例 有没有想过用静态方法会怎么样?

相关推荐

    图解Java单例模式内存分配

    1:虚拟机加载StaticDemo类,保存类型信息到方法区。...  (1)装载,通过类的全名产生对应类的二进制数据流,分析二进制数据流并转换为方法区特定的数据结构,创建对应类的java.lang.Class实例。  (2)链

    西农java实验题

    8. **设计模式**:学习常见的设计模式,如单例模式、工厂模式、观察者模式等,提高代码的可复用性和可维护性。 9. **JDBC数据库操作**:使用Java连接数据库,执行SQL语句,处理结果集。 10. **Java标准库**:熟悉...

    二十三种设计模式【PDF版】

    关于本站“设计模式” Java 提供了丰富的 API,同时又有强大的数据库系统作底层支持,那么我们的编程似乎变成了类似积木的简单"拼凑"和调用, 甚至有人提倡"蓝领程序员",这些都是对现代编程技术的不了解所至. 在...

    Java实验报告及源码

    11. **设计模式**:报告可能涵盖了常见的设计模式,如单例、工厂、观察者模式等,并通过源代码展示了它们在实际项目中的应用。 12. **源代码**:提供的源程序代码是理解和学习Java编程的重要资源,每个文件名可能...

    java学习的全部收藏资料

    3. **设计模式与架构**: 学习常见的设计模式(如工厂模式、单例模式、观察者模式等)和软件架构原则,可以提升代码质量和系统的可维护性。 4. **高级特性**: 包括泛型、反射、注解、枚举、并发编程等,这些都是...

    java源码个人网上银行系统(javase)

    2. **面向对象编程**:深入理解类的设计,包括属性、方法、构造器以及类之间的关系,如单例模式、工厂模式等设计模式的应用。 3. **异常处理**:理解和使用try-catch-finally语句块来捕获和处理程序运行时可能出现...

    java 高级理论-7

    3. **设计模式**:Java中常见的设计模式如单例模式、工厂模式、观察者模式等,是解决常见软件工程问题的通用解决方案。掌握这些模式能提高代码质量和可维护性。 4. **反射机制**:Java反射允许程序在运行时检查类的...

    JAVA实战学习.zip

    13. **设计模式**:在JAVA开发中,设计模式是解决常见问题的最佳实践,如单例模式、工厂模式、观察者模式等,它们提供了可复用的解决方案。 14. **JVM(Java Virtual Machine)**:JAVA程序通过JVM运行,理解JVM的...

    Java个人简历代码

    【Java个人简历代码】是一个关于Java编程语言的项目,它包含了一组代码示例,用于展示个人在Java领域的技能和经验。这个项目可能是为求职者准备的,以便他们在面试或应聘时能展示自己的编程能力。729832422可能是...

    Java工程师成神之路.zip

    8. 设计模式:单例、工厂、观察者等常见设计模式的应用。 9. Java高级特性:Lambda表达式、Stream API、反射等。 作者微信.docx 这可能是一个联系方式文档,作者可能通过微信分享更多的学习资源、解答疑问或建立...

    有关Java的例子(源码)

    10. **设计模式**:在提供的源码中,可能还会发现一些常见的设计模式,如工厂模式、单例模式、观察者模式等,这些都是解决特定问题的通用解决方案。 通过分析和学习这些例子,开发者不仅可以理解Java的基本概念,还...

    一款五子棋小游戏,基于JAVA语言编写。.zip

    8. **设计模式**:为了使代码更易维护和扩展,开发者可能会应用一些设计模式,如单例模式(用于控制资源的唯一性),工厂模式(用于创建对象)或者观察者模式(用于实现事件监听)。 9. **编译与运行**:Java程序...

    java 编程 经典案例集锦

    11. **设计模式**:这些案例可能包含了常见的设计模式,如工厂模式、单例模式、观察者模式、装饰器模式等,这些都是解决特定问题的标准化解决方案,学习者可以通过实践加深对设计模式的理解。 12. **Swing或JavaFX...

    java编写的小的学生信息管理系统

    - **代码结构**:遵循良好的编程规范,使用面向对象的设计模式,如单例模式、工厂模式等,提高代码的可读性和可维护性。 在“小学生管理系统”这个压缩包中,包含了整个项目的源代码和可能的数据库文件。初学者可以...

    java 五子棋项目

    9. **设计模式**:在编写复杂软件系统时,设计模式如单例模式、工厂模式等可以帮助提高代码的可读性和可维护性。开发者可能在项目中应用了这些模式。 10. **版本控制**:项目可能使用Git进行版本管理,通过提交和...

    北邮电子院java作业

    11. **设计模式**:可能会有一些基础的设计模式应用,如单例模式、工厂模式等。 12. **单元测试**:JUnit的使用,进行代码测试以确保其正确性。 13. **图形用户界面(GUI)**:可能涉及到Swing或JavaFX库,用于...

    Java笔记与作业

    1. **设计模式**:单例模式、工厂模式、装饰器模式等常见设计模式的实现。 2. **文件操作**:读取、写入文件,目录操作,文件复制。 3. **多线程**:线程的创建,同步机制(synchronized,wait(),notify()),...

    java学习笔记2

    14. **设计模式**:学习常见的设计模式,如单例模式、工厂模式、观察者模式等,提高代码的可读性和可维护性。 如果压缩包内的"video1"代表视频教程,那么这部分可能包含了讲解上述概念的视觉演示,使得学习更加直观...

    java大学程序设计和java大学基础教程的例子---缺的---ch14

    9. **设计模式**:设计模式是软件开发中的最佳实践,第14章可能介绍一些常见的设计模式,如单例、工厂、观察者、装饰者、适配器等,并讲解如何在Java中应用它们。 10. **JavaFX或Swing图形用户界面**:如果教程覆盖...

Global site tag (gtag.js) - Google Analytics