一、描述
所谓的单例,就是指一个类对象在运行期间就只有一个实例对象,由代码来限制,强制只实例化一次。使用场景一般类似于计数器的需求。使用单例的方式地方大多数可以使用静态方法,这两者有什么区别,在哪种情况下应该使用单例或静态方法呢?
首先两者的区别是:
- 静态类比单例具有更好的性能,因为静态方法在编译其就绑定了。比如一些工具类,java.lang.Math中的类
- 单例类可以继承或实现接口类,但静态类(内部的方法都是静态的)实现非静态方法对它来说无意义。
- 如果需要维护状态信息,则单例比静态类更合适,如java.lang.RunTime类
- 单例可以懒加载
二、实现
实现单例的方式,两种,即为饥饿模式和懒汉模式
饥饿模式
顾名思义就是饥不择食,加载类的时候就创建完成并保存在类中,调用时直接使用即可,一般是使用静态初始化,然后提供静态方法返回单例,java.lang.RunTime类就是如此。
private static Singletons singleton = new Singletons();
public static Singletons getInstance(){
return Singletons.singleton;
}
懒汉模式
就是一开始什么都不做,在使用的时候才去实例化返回。一般有两种实现方式:
1、使用synchronized直接锁方法
private static volatile Singletons singletons = null;
private synchronized Singletons getInstance(){
if(singletons == null) {
singletons = new Singletons();
}
return singletons ;
}
2、双重加锁
private static volatile Singletons singletons = null;
private static final String LOCK = "LOCK";
public static Singletons getSingletonInstance(){
if(singletons == null) {
synchronized (LOCK) {
if(singletons == null){
singletons = new Singletons();
}
}
//init();
}
return singletons;
}
3、静态内部类实现模式
线程安全,调用效率高,可以延时加载
public class Singletons {
//私有化
private Singletons(){}
//静态内部类
private static class SingletonInstance{
private static final Singletons instance=new Singletons();
}
//返回实例
public static Singletons getInstance(){
return SingletonInstance.instance;
}
}
4、枚举类
线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用
public enum Singletons {
//枚举元素本身就是单例
INSTANCE;
//添加自己需要的操作
public void otherOperation(){
}
}