设计模式-Java实现单例模式
单例模式是一种常见的设计模式,许多时候系统只需要一个全局的对象时可以运用单例模式,它确保在系统中某种类只能有一个实例它的特点有:
- 类最多只能拥有一个实例对象
- 类自己创建唯一实例对象
- 类向外提供获取唯一实例对象的方法
单例模式实现方法
单例类通常拥有一个本类对象的引用以及获取本类唯一对象的静态方法,当其他类调用这个静态方法时,如果持有的本类对象的引用为null则创建一个本类对象并赋值给引用,否则直接返回引用对象。还有就是为了防止其他类通过new的方式创建对象,单例类需要将空的构造方法的定义为private。
懒汉式实现
下面实现是单例模式的基本实现,但是存在线程安全问题,不支持多线程
public class Singleton {
private static Singleton instance = null;//单例类提供的唯一对象引用
//为了防止其他类通过 new Singleton() 创建类
private Singleton(){}
public static Singleton getInstance(){
//在第一次获取单例对象时,创建对象,
//注意在多线程中会出现问题,可能会创建多个对象
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
下面的实现是线程安全的,但是大部分时候其实是不需要同步的,所以效率低下
public class Singleton {
private static Singleton instance = null;//单例类提供的唯一对象引用
//为了防止其他类通过 new Singleton() 创建类
private Singleton(){}
/**
* 使用synchronized修饰静态方法,实现线程同步
* 注意synchronized 修饰 static 方法时 获取的是类锁(即Class本身)
*/
public synchronized static Singleton getInstance(){
//在第一次获取单例对象时,创建对象,
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
可以使用双重检验实现多线程下的高效率,下面实现可以大大提高效率,也可以解决线程安全问题
public class Singleton {
private static Singleton instance = null;//单例类提供的唯一对象引用
//为了防止其他类通过 new Singleton() 创建类
private Singleton(){}
public static Singleton getInstance(){
//在第一次获取单例对象时,创建对象,
//第一次检查的目的是当instance 不为null时直接返回instance
if(instance == null){
//加锁实现同步,防止创建多个对象
synchronized (Singleton.class){
/**
* 第二次检查的目的,当系统开始运行,可能会出现很多线程同时调用这个方法,
* 所以一开始可能会有多个线程在锁池中等待获取对象锁,
* 所以一开始可能会有多个线程可以执行到synchronized 代码块中,这样需要防止多次创建对像
*/
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
饿汉式实现
饿汉式实现因为没有锁,所以执行效率会大大提高。但是类在加载时就初始化,没有实现需要时在初始化,可能会浪费内存。
public class Singleton {
//饿汉式是在类加载时就初始化,实现了线程安全,单容易浪费内存
private static Singleton instance = new Singleton();//单例类提供的唯一对象引用
//为了防止其他类通过 new Singleton() 创建类
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
以上是单例模式常见的实现方法,其他的实现方法还有如:静态内部类的实现方法以及枚举的实现方法等,在设计单例模式时要注意如果需要在多线程情景下运行则需要实现线程安全。
对于多线程的知识可以查看这篇博客 [置顶] Java多线程学习(吐血超详细总结)