(有的事情需要提前说明一下,哥们英语不好,在自己学习过程中写的代码有的可能会以中文命名,介意者出门左拐,不介意的继续往下看)
定义:单例模式(Singleton Patern)是Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。
单例模式要做的事情:1、保证一个类只有一个实例;2、为该实例提供一个全局访问点。
单例模式-饿汉式:
package org.example.test07.单例;
//在类加载期间初始化私有的静态实例,保证instance实例创建过程是线程安全的
//不支持延时加载,如果需要创建的对象较大且一直没有使用,就会造成内存的浪费
public class 饿汉式 {
//私有构造方法
private 饿汉式() {
}
//在本类中创建私有静态的全局对象
private static 饿汉式 instance=new 饿汉式();
//提供一个全局的静态访问点,跟随类的加载而加载,供外部获取该单例对象
public static 饿汉式 getInstance(){
return instance;
}
}
单例模式-懒汉式(线程不安全):
package org.example.test07.单例;
public class 懒汉式_线程不安全 {
private 懒汉式_线程不安全(){
}
private static 懒汉式_线程不安全 instance;
public static 懒汉式_线程不安全 getInstance(){
if (instance==null){
instance=new 懒汉式_线程不安全();
}
return instance;
}
}
单例模式-懒汉式(线程安全):
package org.example.test07.单例;
//并发度很低
public class 懒汉式_线程安全 {
private 懒汉式_线程安全(){
}
private static 懒汉式_线程安全 instance;
public static synchronized 懒汉式_线程安全 getInstance(){
if (instance==null){
instance=new 懒汉式_线程安全();
}
return instance;
}
}
单例模式-懒汉式(线程安全双重校验):
package org.example.test07.单例;
//并发度很高
public class 懒汉式_线程安全_双重校验 {
private 懒汉式_线程安全_双重校验(){
}
//添加volatile防止指令重排
private static volatile 懒汉式_线程安全_双重校验 instance;
public static synchronized 懒汉式_线程安全_双重校验 getInstance(){
if (instance==null){
synchronized (懒汉式_线程安全_双重校验.class){
if (instance==null){
//1、分配内存空间
//2、初始化对象
//3、将instance指向分配好的内存空间
instance=new 懒汉式_线程安全_双重校验();
}
}
}
return instance;
}
}
单例模式-饿汉式(静态内部类,防止反射破坏单例):
package org.example.test07.单例;
//被static修饰的不会被gc回收
public class 静态内部类 {
private 静态内部类() {
//防止反射对单例的破坏
if(单例Handler.instance!=null){
throw new RuntimeException("不允许非法访问");
}
}
private static class 单例Handler{
private static 静态内部类 instance=new 静态内部类();
}
public static 静态内部类 getInstance(){
return 单例Handler.instance;
}
//防止反序列化对单例的破坏
//当对象流传输时会检测序列化类中是否包含此方法,在反序列化过程中,该方法会返回原始的单例实例,而不会创建新的实例。可以肯定的是,在这种情况下单例模式的确是可以生效的。
private Object readResolve(){
return 单例Handler.instance;
}
}
单例模式-枚举:
package org.example.test07.单例;
public enum 枚举方式 {
INSTANCE;
private Object data;
public Object getData(){
return data;
}
public void setData(Object data){
this.data=data;
}
public static 枚举方式 getInstance(){
return INSTANCE;
}
}