单例模式的引入。在我们的系统开发之中。我们会有一些对象其实是我们只需要一个。比如:线程池,注册表,缓存等。事实上这些对象只能有一个实例,如果制造出多个实例,就会导致诸多问题如程序行为异常、资源使用过量
首先最简单的单例的实现,我们可以通过将构造器私有化来限制对象的创建,同时提供统一的访问点。下面是代码实现:
public class Singleton {
private Singleton(){
}
private Singleton instance;
public static Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
但是静态方法的单例模式无法应对多线程的操作。多线程对该对象进行操作,可能会获取不止一个该单例对象。
解决办法,只要将getInstance变成同步synchronized方法,多线程引发的问题便几乎能被解决
同步getInstance方法
public class Singleton {
private Singleton(){
}
private Singleton instance;
public static synchronized Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
但是同步一个方法可能造成程序执行效率下降,尤其是在getInstance使用在频繁运行的地方。于是采用
急切实例化方法。
急切实例化方法
public class Singleton {
private Singleton(){
}
private static Singleton instance=new Singleton();
public synchronized Singleton getInstance(){
return instance;
}
}
利用此方法,jvm在加载这个类时马上创建此唯一的单例模式。JVM保证在任何线程访问instance静态变量之前,一定先创建此实例。
还用一种方法双重检查加锁。可以在getInstance()中减少使用的同步
public class Singleton {
private Singleton(){
}
private volatile static Singleton instance=new Singleton();;
public synchronized Singleton getInstance(){
if(instance==null)
{
synchronized (Singleton.class) {
if(instance==null)
instance=new Singleton();
}
}
return instance;
}
}
单例模式优点
- 1 在内存中只有一个对象,节省内存空间。
- 2 避免频繁的创建销毁对象,可以提高性能。
- 3 避免对共享资源的多重占用。
- 4 可以全局访问。
适用场景
- 1 需要频繁实例化然后销毁的对象。
- 2 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 3 有状态的工具类对象。
- 4 频繁访问数据库或文件的对象。
- 5 以及其他我没用过的所有要求只有一个对象的场景
-6 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
-7 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。