定义
单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。
生活场景
1、人间的太阳、月亮以及“人”自己不也是唯一的存在也无比的稀有。
2、公司的老板也就是CEO首席执行官。
代码演示
饿汉式
优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。
缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费了内存。
package com.util;
public class HungrySingleton {
private static final HungrySingleton singleton = new HungrySingleton();
private HungrySingleton(){ }
public static HungrySingleton getInstance(){
return singleton;
}
}
package com.util;
public class Test {
public static void main(String[] args) {
HungrySingleton singleton = HungrySingleton.getInstance();
HungrySingleton singleton1 = HungrySingleton.getInstance();
System.out.println("singleton:"+singleton);
System.out.println("singleton1:"+singleton1);
}
}
执行结果:
懒汉式
package com.util;
public class LazySingleton {
private LazySingleton(){ }
private static LazySingleton singleton = null;
public synchronized static LazySingleton getInstance(){
if(singleton == null){
singleton = new LazySingleton();
}
return singleton;
}
}
package com.util;
public class Test {
public static void main(String[] args) {
LazySingleton singleton = LazySingleton.getInstance();
LazySingleton singleton1 = LazySingleton.getInstance();
System.out.println("singleton:"+singleton);
System.out.println("singleton1:"+singleton1);
}
}
执行结果:
双重检查锁
线程安全、延迟加载、效率较高,volatile保证可见性和禁止指令重排序。
package com.util;
public class LazyDoubleCheckSingleton {
private static volatile LazyDoubleCheckSingleton singleton = null;
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
if(singleton == null){
synchronized (LazyDoubleCheckSingleton.class){
if(singleton==null){
singleton = new LazyDoubleCheckSingleton();
}
}
}
return singleton;
}
}
package com.util;
public class Test {
public static void main(String[] args) {
LazyDoubleCheckSingleton singleton = LazyDoubleCheckSingleton.getInstance();
LazyDoubleCheckSingleton singleton1 = LazyDoubleCheckSingleton.getInstance();
System.out.println("singleton:"+singleton);
System.out.println("singleton1:"+singleton1);
}
}
执行结果:
静态内部类
package com.util;
/**
* 当使用到该类时会先初始化内部类
*/
public class LazyInnerClassSingleton {
private static LazyDoubleCheckSingleton singleton = null;
private LazyInnerClassSingleton(){
if(LazyHolder.LAZY != null){
throw new RuntimeException("不允许创建多个实例,防止暴力强吻");
}
}
public static final LazyInnerClassSingleton getInstance(){
return LazyHolder.LAZY;
}
private static class LazyHolder{
private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
}
}
package com.util;
public class Test {
public static void main(String[] args) {
LazyInnerClassSingleton singleton = LazyInnerClassSingleton.getInstance();
LazyInnerClassSingleton singleton1 = LazyInnerClassSingleton.getInstance();
System.out.println("singleton:"+singleton);
System.out.println("singleton1:"+singleton1);
}
}
执行结果:
序列化式
package com.util;
import java.io.Serializable;
public class SeriableSingleton implements Serializable {
private SeriableSingleton(){}
private static final SeriableSingleton singleton = new SeriableSingleton();
public static SeriableSingleton getInstance(){
return singleton;
}
}
package com.util;
import java.io.Serializable;
public class SeriableSingleton implements Serializable {
private SeriableSingleton(){}
private static final SeriableSingleton singleton = new SeriableSingleton();
public static SeriableSingleton getInstance(){
return singleton;
}
}
执行结果:
增加readResolve()方法
package com.util;
import java.io.Serializable;
public class SeriableSingleton implements Serializable {
private SeriableSingleton(){}
private static final SeriableSingleton singleton = new SeriableSingleton();
public static SeriableSingleton getInstance(){
return singleton;
}
private Object readResolve(){
return singleton;
}
}
执行结果:
注册式
package com.util;
import java.util.HashMap;
import java.util.Map;
public class ContainerSingleton {
private ContainerSingleton(){ }
private static Map<String,Object> ioc= new HashMap<>();
public static Object getBean(String className){
synchronized (ioc){
if(!ioc.containsKey(className)){
Object obj = null;
try {
obj = Class.forName(className).newInstance();
ioc.put(className,obj);
}catch (Exception e){
e.printStackTrace();
}
return obj;
}else{
return ioc.get(className);
}
}
}
}
package com.util;
public class User {
private String userId;
private String userName;
private String userPassword;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
}
package com.util;
public class Test {
public static void main(String[] args) {
Object s1 = ContainerSingleton.getBean("com.util.User");
Object s2 = ContainerSingleton.getBean("com.util.User");
System.out.println("s1:"+s1);
System.out.println("s2:"+s2);
}
}
执行结果:
枚举式
package com.util;
public enum EnumSingleton {
INSTANCE;
private EnumSingleton(){
System.out.println("init");
}
public void helloWorld(){
System.out.println("say hello good");
}
}
package com.util;
public class Test {
public static void main(String[] args) {
EnumSingleton s1 = EnumSingleton.INSTANCE;
s1.helloWorld();
EnumSingleton s2 = EnumSingleton.INSTANCE;
s2.helloWorld();
EnumSingleton s3 = EnumSingleton.INSTANCE;
s3.helloWorld();
}
}
执行结果:
init只调用了一次,所以符合单例模式的规则。