u011700281的专栏

原来转载过一篇关于单例模式的博客

现在自己由于实现一些管理器(比如 mysq了连接的管理器,redis的连接管理器,以及config的连接管理器),经常用到单例模式,不过,公司内的单例模式的实现方法有很多,自己也跟着总结一下。

首先,为什么需要单例模式呢?比如,你需要获得一个mysql连接,你肯定希望所有mysql的连接池是被一个对象管理的,而不希望你从这个对象可以获得连接,从另一个对象也可以获得连接,所以,就很有必要让这个对象唯一。这时候就需要实现单例模式了。

单例的实现,根本上来说,是要让构造函数私有化,因为一旦构造函数暴露,总是可以通过new 来初始化这个对象的。

构造函数私有了,也就是只有本类之内能调用这些方法,所以下面介绍几种实现。

1.最简单的单例

public class Singleton {private final static Singleton instance = new Singleton();private Singleton(){}// some other code;}这个简单粗暴,直接设置一个静态变量,由于静态变量是类共有的,所有只会被调用一次。

简单粗暴,但是会有一些问题。

第一,这个类在加载的时候就必须创建这个对象,,假设创建这个类的代价很高,那在服务启动时候,有很多这样的类的话,就导致速度很慢。

第二,假设这个类的构造函数调用了其他类的静态资源,这些静态变量这时候并没有被加载进来,这就会出现问题。

如果创建对象没什么代价,而且也不会用到其他变量的时候,使用这个方法还是很简单的。

2.延迟创建

private static Singleton instance = null;private Singleton(){}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}这个方法,乍一看不错啊,只有当使用的时候才会创建这个对象。而且,这个方法确实不错啊,但是并发情况下这是很渣的。

3.于是看到一种比较狠的,使用了syschonised

public class Singleton {private static Singleton instance = null;private Singleton(){}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance =new Singleton();}}}return instance;}}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">在这个方法中调用了同步锁,所以不会有并发问题。</span>

4.使用holder的方法,将管理实例完全封装起来

也就是实现一个内部类

public class Singleton {private Singleton(){}private static class SingletonHolder{private static Singleton instance = new Singleton();}}这个内部类对于外界来说完全透明,而且这个私有变量对外部的类来说是可以访问的,由于这个内部类只在使用的时候加载并且创建该实例,也是延迟创建的。

5.使用枚举,枚举天生就是单例,所以很好用的。

6.使用spring托管,这个不用说了。

以上几种方式,各有优缺点把,使用哪个就看需要。

人之所以能,是相信能。

u011700281的专栏

相关文章:

你感兴趣的文章:

标签云: