1.Java的单例模式有7中写法,我们来一一介绍一下。
2.懒汉式
public class Singleton1 {
private Singleton1() {
}
private static Singleton1 instance;//懒汉式
public static Singleton1 getInstance(){//存在线程安全问题,假如两个线程同时判断到instance为空,就会创建两个对象了。
if (instance == null)
instance = new Singleton1();
return instance;
}
}
它是线程不安全的,所以不建议使用。
3.线程安全的懒汉式
public class Singleton2 {
private Singleton2() {
}
private static Singleton2 instance;//懒汉式
public static synchronized Singleton2 getInstance(){//不存在线程安全问题,但每次获取对象时,都需要持有锁;在Java中锁是很耗资源和性能的
if (instance == null)
instance = new Singleton2();
return instance;
}
public static Singleton2 getInstance1(){//不存在线程安全问题,但每次获取对象时,都需要持有锁;在Java中锁是很耗资源和性能的
synchronized (Singleton2.class) {
if (instance == null)
instance = new Singleton2();
}
return instance;
}
}
就是加锁的方式,但是单例new就执行一次,多数情况都是要去调用getInstance方法;这里加了锁,所以每次获取对象时都要去过去锁,很耗资源和性能,很耗时;也不建议使用。
4.懒汉式,双重检验锁
public class Singleton3 {
private Singleton3() {
}
private static Singleton3 instance;//懒汉式,双重检验锁
public static Singleton3 getInstance(){//不存在线程安全问题,只有在为空时才加锁,然后再判空;减少了获取锁的消耗
if (instance == null){
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
这种写法是线程安全的,并且不会很耗时;但写法稍微复杂。
5.饿汉式
public class Singleton4 {
private Singleton4() {
}
private static Singleton4 instance = new Singleton4();//饿汉式,如果没有使用到,会浪费内存,因为类一加载就创建对象了
public static Singleton4 getInstance(){
return instance;
}
}
这种写法是线程安全的,但在类加载时就会申请内存;假如开始没有使用的话,一定程度上浪费了内存空间;不太符合程序的懒加载思想。
6.饿汉式
public class Singleton5 {
private Singleton5() {
}
private static Singleton5 instance;//饿汉式,如果没有使用到,会浪费内存,因为类一加载就创建对象了
static {
instance = new Singleton5();
}
public static Singleton5 getInstance(){
return instance;
}
}
它和上面的一样的,只是把静态变量写到了静态代码块中。
7.饿汉式静态内部类
public class Singleton6 {
private Singleton6() {
}
private static class Singleton5Holder{
private static Singleton6 instance = new Singleton6();
}
public static Singleton6 getInstance(){//静态内部类的方式,只有调用此方法了,才会创建对象,节省内存
return Singleton5Holder.instance;
}
}
这里使用了静态内部类的方法来返回对象;这样在类加载时,不会创建对象;当使用时,会调用一次静态内部类,创建好对象;符合懒加载思想,也不会造成内存浪费;写法相对与懒汉式也简单;所以建议使用这种方式。
8.枚举类
public enum Singleton7 {
INSTANCE;
//查看编译后的class文件,发现自动添加了私有的无参构造方法;和单例是很像的;
// 也就是说这个类的实例对象INSTANCE是唯一的,这就是单例
//下面就可以写各种对这个类的方法或业务逻辑处理了;
public void method(){
}
}
就是使用一个枚举来表示;但实际工作中很少使用过这种方式,至少我本人是这样的;Effective Java第二版中倒是建议使用这种方式。