题目:设计一个类,我们只能生成该类的一个实例。
要生成单例模式,有以下几种实现方式:
方法一:懒汉式(只适用于单线程)
要只能创建一个单例,需要把构造函数设为私有函数,并且创建一个私有静态实例,只有当该实例为null时,才能创建。
只有在需要的时候才会创建。
public class Singleton1{
private Singleton{
}
private static Singleton1 instance=null;
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton1();
}
return instance;
}
}
缺点:当在多线程情况下,如果有两个线程同时运行到判断instance是否为空时,instance没有被创建,那么两个线程都会创建一个实例,此时不再满足单例模式要求。
方式二:饿汉式(可以在多线程环境下工作,但效率不高)
public class EagerSingleton {
private static EagerSingleton instance=new EagerSingleton();
private EagerSingleton(){}
public static synchronized EagerSingleton getInstance() {
return instance;
}
}
缺点:在两个线程想同时创建一个实例时,一个线程得到同步锁,另一个线程只能等待。第一个线程完成之后,第二个线程进行加锁,他发现实例已被创建,则不会重复创建。加锁是一个非常耗时的操作,在没有必要的时候需要避免。
方式三:使用同步关键字双重加锁
public class DoubleLockSingleton {
private static volatile DoubleLockSingleton instance;//volatile关键字是必须的,用以确保多线程共享实例
private DoubleLockSingleton(){}
public static DoubleLockSingleton getInstance(){
if(instance==null){
synchronized(DoubleLockSingleton.class){
if(instance==null){
instance=new DoubleLockSingleton();
}
}
}
return instance;
}
}
当instance没有被创建时,加锁,反之不加锁,只有在第一次创建时instance为null,所以只有在第一次创建实例时需要加锁,减少了不必要的时间消耗。
缺点:用两个if判断,代码实现复杂,容易出错。
方法四:实现按需创建实例
public class SingletonBest {
private SingletonBest(){}
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
* @author DELL
*
*/
public static class Singleton{
private static SingletonBest instance=new SingletonBest();
}
/**
* 静态初始化器,由JVM来保证线程安全
* @return
*/
public static SingletonBest getInstance(){
return Singleton.instance;
}
}
该方法使用了静态成员内部类,只有在调用Singleton.instance时才会被创建,实现了按需创建的要求。
方法五:单元素枚举
public enum EnumSingleton {
//定义一个枚举的元素,它就代表了Singleton的一个实例。
instance;
public void singletonOperation(){
//功能处理
}
}
通过这几种方式实现单例模式的创建,不仅让我学到了单例模式的思想,更加学到了要实现一个优秀的算法,还需思考更多。编程更多的是要有一种思想,以后还要多刷题,达到思想更加符合一个程序员。