返回首页

单例模式不单例

时间:2009-01-14 23:19来源:xiaowen.net 作者:xiaowen.net 点击:
单例模式是非常普遍和有用的模式,记得教我们Java的老师告诉我们单例模式的时候,用系统垃圾箱来举例子,一个系统只有一个垃圾箱,任何地方打开内容都是一样的。实际编程的时候我也经常用到,像系统配置文件对象,事物管理对象等等,一个系统只有一个才不会出现冲突。
  单例模式是非常普遍和有用的模式,记得教我们Java的老师告诉我们单例模式的时候,用系统垃圾箱来举例子,一个系统只有一个垃圾箱,任何地方打开内容都是一样的。实际编程的时候我也经常用到,像系统配置文件对象,事物管理对象等等,一个系统只有一个才不会出现冲突。

但今天看到一篇文章,里面有句话:单例对象在序列化后反序列化会出现多个实例。

先说序列化,序列化是Java中的特性(或许其他语言也有),具体原理不清楚,还没有想去了解。但任何需要将一个内存中的Java对象保存在硬盘, 或者在网络中传输(也可以理解为将该对象从内存中拿出来放到另一个地方),该对就必须implements Serializable,这样才能被序列化为二进制代码进行传输。

从序列化和反序列化的过程来看,使单例对象出现多个实例是绝对有可能的。因为单例类隐藏构造方法,禁止直接实例化。而反序列化不需要构造方法,直接由二进制代码生成,从而绕开private的构造方法。

代码说明一切

先写一个单例类

  1. public class Singleton implements Serializable{
  2.        
  3.         private static final long serialVersionUID = 2430968225406982467L;
  4.  
  5.         private static Singleton instance;
  6.  
  7.         private Integer counter = new Integer(0);
  8.  
  9.         private Singleton() {
  10.                 counter = 0;
  11.         }
  12.  
  13.         public static synchronized Singleton getInstance() {
  14.                 if (instance == null){
  15.                         instance = new Singleton();
  16.                 }
  17.                 return instance;
  18.         }
  19.  
  20.         public synchronized int getNext() {
  21.                 return ++counter;
  22.         }
  23.  
  24. }

该类很简单,计数,还特别synchronized了getNext方法,讲究一下严谨。

写个类测试

  1. public class Test {
  2.         public static void main(String [] args) throws FileNotFoundException, IOException, ClassNotFoundException{
  3.                 Singleton singleton = Singleton.getInstance();    //第一个对象
  4.                 System.out.println(singleton.getNext());            //打印  1
  5.                
  6.                
  7.                 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj"));
  8.                 oos.writeObject(singleton);                             //将该对象写在object.obj文件中
  9.                
  10.                
  11.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.obj"));
  12.                 Singleton singleton2 = (Singleton)ois.readObject();     //再读出来
  13.        
  14.        
  15.                 System.out.println(singleton.getNext());       //打印2
  16.                 System.out.println(singleton2.getNext());     //打印2
  17.                 System.out.println(singleton2 == singleton)//打印false
  18.         }
  19. }

结果确实如此,单例类出现了两个不同的对象。乍看起来这种情况不可能出现,但前不久我的一个项目中,需要在一台机器或多台机器(用网络连接)中,程 序需要互为主备,运行的只用一个,其他做数据同步,但主程序死掉后,第一备用程序需要第一时间顶起来,保持系统正常。在数据同步的部分,对象就是序列化后 网络传输进行同步。同步的还包括配置管理对象,就是配置文件,都要按照一主程序的配置文件运行,不然会很麻烦。这时候需要考虑同步的配置文件对象的单例问 题。看来在同步的时候,对于单例对象要进行特殊处理,不然就有的好看了,死都不知道怎么死的。

顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
  • 上一篇:没有了
  • 下一篇:没有了
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
小朱 查看详细资料 发送留言 加为好友 用户等级:超级会员 注册时间:2008-11-18 17:11 最后登录:2013-12-24 23:12
推荐内容
  • 单例模式不单例

    单例模式是非常普遍和有用的模式,记得教我们Java的老师告诉我...

热点内容