单列java_单例 (JAVA)

java中单例模式是一种常见的设计模式,以下是它的特点:

单例类只能有一个实例。

单例类必须自己创建自己的唯一实例。

单例类必须给所有其他对象提供这一实例

第一种(懒汉,线程不安全):

1 public class Singleton {

2     private static Singleton instance;

3

private Singleton (){}

4     public static Singleton getInstance() {

5     if (instance == null) {

6         instance = new Singleton();

7     }

8     return instance;

9     }

10 }

11

懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间

由于懒汉式的实现是线程安全的,这样会降低整个访问的速度,而且每次都要判断.

第二种(懒汉,线程安全):

1 public class Singleton {

2     private static Singleton instance;

3

private Singleton (){}

4     public static synchronized Singleton getInstance() {

5     if (instance == null) {

6         instance = new Singleton();

7     }

8     return instance;

9     }

10 }

11

第三种(饿汉):

1 public class Singleton {

2     private static Singleton instance = new Singleton();

3

private Singleton (){}

4     public static Singleton getInstance() {

5     return instance;

6     }

7 }

8

第四种(饿汉,变种):

1 public class Singleton {

2     private Singleton instance = null;

3     static {

4     instance = new Singleton();

5     }

6

private Singleton (){}

7     public static Singleton getInstance() {

8     return this.instance;

9     }

10 }

11

表面上看起来差别挺大,其实更第三种方式差不多,都是在类初始化即实例化instance。

第五种(静态内部类):

1 public class Singleton {

2     private static class SingletonHolder {

3     private static final Singleton INSTANCE = new Singleton();

4     }

5

private Singleton (){}

6     public static final Singleton getInstance() {

7         return SingletonHolder.INSTANCE;

8     }

9 }

10

优点:加载时不会初始化静态变量INSTANCE,因为没有主动使用,达到Lazy loading

第六种(枚举):

1 public enum Singleton {

2     INSTANCE;

3     public void whateverMethod() {

4     }

5 }

6

优点:不仅能避免多线程同步问题,而且还能防止反序列化

第七种(双重校验锁):

1 public class Singleton {

2     private volatile static Singleton singleton;

3

private Singleton (){}

4     public static Singleton getSingleton() {

5     if (singleton == null) {

6         synchronized (Singleton.class) {

7         if (singleton == null) {

8             singleton = new Singleton();

9         }

10         }

11     }

12     return singleton;

13     }

14 }

15

总结

有两个问题需要注意:

1、如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些

servlet容器对每个

servlet使用完全不同的类  装载器,这样的话如果有两个

servlet访问一个单例类,它们就都会有各自的实例。

2、如果

Singleton实现了

java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。

对第一个问题修复的办法是:

1 private static Class getClass(String classname)

2                                          throws ClassNotFoundException {

3       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

4

5       if(classLoader == null)

6          classLoader = Singleton.class.getClassLoader();

7

8       return (classLoader.loadClass(classname));

9    }

10 }

11

对第二个问题修复的办法是:

1 public class Singleton implements java.io.Serializable {

2    public static Singleton INSTANCE = new Singleton();

3

4    protected Singleton() {

5

6    }

7    private Object readResolve() {

8             return INSTANCE;

9       }

10 }

11

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值