单例模式是设计模式中比较简单的一种模式,也是使用的比较多的一种模式。
特别是在某些对象只需要一个时,比如线程池、缓存、日志对象、注册表对象等。
如果创建了多个,可能会导致很多问题。比如程序行为异常、资源使用过量等。
单例模式确保程序中一个类最多只有一个实例。
单例模式提供访问这个实例的全局点。
在Java中单例模式需要:私有构造器、一个静态方法、一个静态变量。
如果使用多个类加载器,可能会导致单例失效而产生多个实例。
单例模式确保一个类只有一个实例,并提供一个全局的访问点。
- 下面为延迟加载的单例模式(懒汉式):
/**
当需要用到对象的时候,再创建对象(延迟加载方式)(一开始是null)第二次直接返回之前创建好的对象,不占内存;
一个线程对象的时候,这种方式线程是安全的;
多个线程对象的时候,这种方式线程是不安全, 可以同步机制处理;
*/
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
- 处理多线程:需要将getInstance()添加“双重检查加锁”,多线程的问题就可以轻松解决。
/**
解决多线程不安全问题
*/
public class Girl {
//创建本类对象的引用
private static Girl g = null;
//构造方法私有
private Girl(){
}
//提供一个公共的方法让外界访问,获取到已创建的本类对象
//第一次访问该方法,创建对象
//之后再访问该方法,返回以前创建好的对象
public static Girl getInstance(){
//第一次访问该方法,创建对象
if (g == null) {
synchronized(Girl.class){
if (g == null) {
g = new Girl();
}
}
}
//之后再访问该方法,返回以前创建好的对象
return g;
}
}
- 如果应用程序总是创建并使用单例模式、或者在创建和运行时负担不太繁重,可以急切创建实例(饿汉式):
/**
直接创建对象,这样是线程安全的
*/
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static synchronized Singleton getInstance() {
return uniqueInstance;
}
}