单例模式是一种创建型模式。它保证一个类只有一个实例,并且只提供一个函数接口让其他类获取到这个实例。
1.优缺点
1.1优点
单例类只有一个实例,节省内存开销,避免对资源的多重占用。例如一个文件操作,由于只有一个实例存在,避免同一资源同时操作,对于一些频繁创建销毁的对象,使用单例模式可以提高系统性能
1.2缺点
扩展性差,获取对象时不能用new,单例对象如果持有Context容易造成内存泄露
2.单例模式的创建方式
2.1饿汉式
/**
* 饿汉式单例模式,在声明的时候已经初始化
*
* 1.构造方法使用private修饰,保证外部无法访问
* 2.在声明对象是初始化
* 3.static关键字修饰静态变量
* 4.final关键字保证只初始化一次
*/
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
饿汉式在类加载时就完成了实例化,避免了多线程的同步问题,获取实例的速度快。但类加载比较慢,没有达到懒加载的效果,如果一直未使用过该实例,就造成了内存浪费
2.2懒汉式
2.2.1普通的懒汉式,线程不安全
/**
* 普通的懒汉式
*
* 1.构造方法使用private修饰,保证外部无法访问
* 2.调用getInstance()才会初始化
* 3.static关键字修饰静态变量
*/
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这是懒汉式最简单的写法,只有在第一次被访问时才会实例化,达到了懒加载的效果,但会出现多线程的安全问题。加入对象还没有被实例化,然后有多个线程同时访问,就可能会多次实例化,所以这种写法不采用
2.2.2同步锁的懒汉式,线程完全
对getInstance()方法进行加锁,保证同一时刻只能有一个线程访问并得到实例,但synchronized是修饰整个方法,每个线程访问都要进行同步
/**
* 加锁的懒汉式
*
*/
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2.3双重锁
/**
* 双重锁
* 构造函数使用private修饰,外部无法访问
* 在使用的时候调用getInstance()进行初始化
* synchronized线程安全,保证多线程情况下的唯一性
* 两次判空避免多次同步
*/
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
2.4静态内部类
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
private static class SingletonHelper {
private static final Singleton INSTANCE = new Singleton();
}
}