一、什么是Singleton模式?
Singleton模式就是平常所说的单例模式,简单来说就只有一个实例。在使用java.lang.String的时候,将不同的字符串赋给String引用,其实就是创建了一个String对象实例,当有1000个不同的字符串创建的时候,就会出现1000个实例。有时候,我们只想在程序里面创建一个实例,譬如Hibernate的SessionFactory,那么我们可以使用Singleton模式来设计某一个类从始至终,程序调用的都是属于同一个实例。
二、Singleton模式的思想
实现单例的类里面有一个私有的本类对象属性;一个私有的构造方法,说明外面的类不可以通过new的方式来创建该对象;还有一个public的getInstance方法,用于给外面的类调用获取Singleton对象实例。
三、具体实例
实现Singleton模式有多种方式,主要分为两大类:懒汉模式和饿汉模式。
所谓的懒汉模式,就是比较“懒”,需要调用的时候,才去加载资源(创建实例);饿汉模式就跟懒汉模式相反,在程序启动,类加载的时候就顺便加载实现了。
1、懒汉模式(最常见,也最安全高效)
package com.cjs.Singleton; public class SingletonLazy { private static SingletonLazy singletonLazy; private SingletonLazy() { } public static SingletonLazy getInstance() { if (singletonLazy == null) { synchronized (SingletonLazy.class) { if (singletonLazy == null) { singletonLazy = new SingletonLazy(); } } } return singletonLazy; }}
为什么说是最常见,也最安全高效?因为懒汉模式可以合理利用分配资源,而且使用synchronnized锁可以保证创建实例的时候不被其他线程占用。
编写一个Main类,运行一下:
package com.cjs.Singleton; public class Main { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { SingletonLazy singletonLazy = SingletonLazy.getInstance(); System.out.println(singletonLazy.hashCode()); } }; for (int i = 0; i < 5; i++) { try { Thread t = new Thread(r); t.start(); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
输出:
它们的hascode都是一样的值,说明它们获取的实例都是同一个。
2、饿汉模式
饿汉模式实现Singleton模式,有分类好几种:静态生成;静态内之类生成;序列化与反序列化;枚举实现;
他们实现的原理都一样,都是程序启动的时候,就进行加载创建实例。下面举个简单的例子:
package com.cjs.Singleton; public class SingletonStatic { private static class MySingletonStatic{ private static SingletonStatic singletonStatic = new SingletonStatic(); } private SingletonStatic() { } public static SingletonStatic getInstance() { return MySingletonStatic.singletonStatic; }}
Main类:
package com.cjs.Singleton; public class Main { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() {// SingletonLazy singletonLazy = SingletonLazy.getInstance(); SingletonStatic singletonStatic = SingletonStatic.getInstance(); System.out.println(singletonStatic.hashCode()); } }; for (int i = 0; i < 5; i++) { try { Thread t = new Thread(r); t.start(); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
输出: