单例模式:它是一种对象创建模式,他可以确保一个类中只产生一个实例。
1.对于频繁使用的对象,可以省略创建对象所发费的时间,这对于重量级对象而言,是一笔非常可观的系统开销。
2.由于new的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。
单例模式的核心在于通过一个接口返回唯一的对象实例,一个简单的单例实现如下:
public class Singleton{
private Singleton(){
System.out.println("Singleton is create");
}
private static Singleton instance=new Singleton();
public static Singleton getInstance(){
return instance;
}
}
这个饿汉式一般都是大家所熟知的,粗体字已经表明了它实现功能所在。但它的缺点也是很明显的,我们若没有调用这个实例,但这个实例依然已经被创建了,而我们的初衷就是为了避免重量级对象无故创建。(这里的调用是指这个类里面还有其他方法或变量,而你去引用了,进而加载了这个类,我们的静态实例同时也就创建了。但如果单纯向上面实例一样,这个类只为了调用它的getInstance()方法,其实我们考虑的这些都是没问题的,甚至在并发中也是可行的)
那么我们来对他的改进一下
public class Singleton{
private Singleton(){
System.out.println("Singleton is create");
}
private static Singleton instance=null;
public static Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
我们初期定义的实例为null,等到我们需要的时候再去实例化。这就是懒汉式单例模式,懒汉式虽然可以解决我们需要用的时候才去实例化,但是在并发过程中就会出现问题。倘若线程1去调用getInstance()方法时,判断instance为null,开始创建实例,在这时,线程2同样调用这个getInstance()方法时,instance仍然为null,也去创建了实例,这就造成了实例了多个对象,违背了我们初衷。
那么我们在这个方法上加个synchronized进行同步
public static synchronized Singleton getInstance(){
这样可以解决并发创建多个实例问题,但同步带来的就是阻塞,倘若有多个线程同时去调用这个方法,它必须等上一个线程执行完这个方法,下一个才能开始调用,这样就会浪费时间。其实在我看过的设计模式视频也好,其他人的博客也好,还有很多种多单例模式的优化,但今天我发现了一种很精简,易懂,实用的方法。
public class Singleton{
private Singleton(){
System.out.println("Singleton is create");
}
private static class SingletonHolder{
private static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
在这个实现中,单例模式使用内部类来维护单例实例,当Singleton被加载时,内部类不会被初始化。而当getInstance()调用时,才会加载内部类SingletonHolder,从而初始化instance,而且多并发也是可行的。
有问题请赐教,java讨论q群:462535592
参考书:Java程序性能优化