单例模式介绍
所谓单例模式,就是采取一定的方法保证在整个的软件系统中,只能存在一个对象实例,并且该实例只提供一个取得其对象实例的方法(静态方法)
单例模式有八种方法
1、饿汉式(静态常量)
2、饿汉式(静态代码块)
3、懒汉式(线程不安全)
4、懒汉式(线程安全,同步方法)
5、懒汉式(线程安全,同步代码块)
6、双重检查
7、静态内部类
8、枚举
饿汉式(静态常量)
思路
1、构造器私有化(防止new)
2、类的内部创建对象
3、向外暴露一个静态的公共方法.getInstance
代码
class Singleton { private Singleton() { } private final static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } }
优缺点
1、优点:这种写法比较简单,就是在类装在的时候就完成实例化.避免线程同步问题.
2、缺点:在类装载的时候,就已经创建对象,若不需要用到可能会造成内存浪费.
3、结论:可用,但是可能造成内存浪费
饿汉式(静态代码块)
class Singleton { private final static Singleton instance; private Singleton() { } static { instance = new Singleton(); } public static Singleton getInstance() { return instance; } }
和上面一样,也是类加载的时候创建对象,不能确保是否还有其他静态方式创建对象,如果用不到时,可能造成内存浪费.
懒汉式(线程不安全)
class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { return new Singleton(); } return instance; } }
1、起到了lazy loading的效果,但是只能在单线程下使用
2、线程不安全
3、在实际开发中不可用
懒汉式线程安全
class Singleton{ private static Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance(){ if (instance == null){ return new Singleton(); } return instance; } }
1、线程安全
2、效率低
懒汉式(不可用,线程不安全)
class Singleton { private static Singleton instance; private Singleton() { } public Singleton getInstance(){ if (instance == null){ synchronized (Singleton.class){ return new Singleton(); } } return instance; } }
1、线程不安全
2、效率低
双重检查判断
class Singleton { private static Singleton instance; private Singleton() { } public Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { return new Singleton(); } } } return instance; } }
1、线程安全
2、效率较高,推荐使用
静态内部类
class Singleton { private static volatile Singleton instance; private Singleton() { } private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
1、用类加载的机制保证初始化时只有一个线程(静态内部类只有用到时才加载,且线程安全).
2、静态内部类方式在Singleton类被装载时并不会立即实例化(静态内部类只有用到时才加载),而是调用时,才完成类加载,也就是调用getInstance时
3、只有当静态内部类被主动调用的时候,JVM才会去初始化这个静态内部类,且JVM初始化类是线程安全的。
4、总结:线程安全,利用静态内部类实现lazy loading效率高,推荐使用
枚举法
enum Singleton{ INSTANCE; }
1、借助JDK1.5中添加的枚举来实现单例模式.不仅线程安全,还能防止反序列化重新创建新的对象(不能被反射创建)
2、极度推荐
单例模式注意事项和细节说明
1、单例模式保证系统内中该类只存在一个对象,节省了系统资源,对于一些需要频繁销毁的对象,用单例模式可以提高系统性能(创建销毁只需一次)
2、当想实例化一个单例类的时候,必须记住使用相应的获取对象的方法,而不是使用new
3、使用场景,需要频繁创建和销毁对象,创建重量级对象(消耗的资源,时间多),但又经常使用的对象、如工具类对象、频繁访问的数据库对象、或文件对象(数据源、session工厂)
经典应用场景
//JDK中,java.lang.Runtime public class Runtime { private static Runtime currentRuntime = new Runtime(); /** * Returns the runtime object associated with the current Java application. * Most of the methods of class <code>Runtime</code> are instance * methods and must be invoked with respect to the current runtime object. * * @return the <code>Runtime</code> object associated with the current * Java application. */ public static Runtime getRuntime() { return currentRuntime; } /** Don't let anyone else instantiate this class */ private Runtime() {}