JAVA设计模式---单例模式你知道吗
作者:大忽悠爱忽悠
这篇文章主要给大家介绍了关于Java单例模式,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
单例模式的介绍
单例模式实现的八种方式
饿汉式
静态常量
步骤:
1.构造器私有化(防止new)
2.类的内部创建对象
3.向外暴露一个静态的公共方法—getInstance
//饿汉式静态常量 class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 private final static Singleton instance=new Singleton(); //提供一个公有的静态方法,返回一个实例对象 public static Singleton getInstance() { return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
静态代码块
//饿汉式静态常量 class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 private static Singleton instance; //在静态代码块中,创建单例对象 static { instance=new Singleton(); } //提供一个公有的静态方法,返回一个实例对象 public static Singleton getInstance() { return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
静态代码块的优缺点
懒汉式
线程不安全的写法
class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 private static Singleton instance; //提供一个公有的静态方法 //当使用该方法时,才去创建实例对象 //即懒汉式 public static Singleton getInstance() { if(instance==null) { instance=new Singleton(); } return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
线程安全,同步锁—效率低,不推荐
class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 private static Singleton instance; //提供一个公有的静态方法 //当使用该方法时,才去创建实例对象 //即懒汉式 //给当前静态方法加上一个同步锁,这样所有的对象就是一把锁 //多个对象同时调用此方法,会按顺序依次调用 public static synchronized Singleton getInstance() { if(instance==null) { instance=new Singleton(); } return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
线程安全,同步代码块—无法解决线程安全问题,不推荐
class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 private static Singleton instance; //提供一个公有的静态方法 //当使用该方法时,才去创建实例对象 //即懒汉式 public static Singleton getInstance() { if(instance==null) { //锁的是代码块 //锁的对象是当前类的字节码文件对象,即当前类的所有势力对象拥有一把锁 synchronized(Singleton.class) { instance=new Singleton(); } } return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
双重检查—解决线程安全和懒加载问题–推荐使用
class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态常量 //volatile 保证变量在多线程下的可见性,即每个线程获取到当前变量的值是最新的值 private static volatile Singleton instance; //提供一个公有的静态方法 //当使用该方法时,才去创建实例对象 public static Singleton getInstance() { //加入双重检查问题,解决线程安全,同时解决懒加载问题 if(instance==null) { //锁的是代码块 //锁的对象是当前类的字节码文件对象,即当前类的所有势力对象拥有一把锁 synchronized(Singleton.class) { if(instance==null) { instance=new Singleton(); } } } return instance; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
静态内部类—可以实现懒加载,线程安全,推荐使用
静态内部类在调用时,才会加载
当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的
class Singleton { //构造器私有化,外部不能new private Singleton(){} //静态内部类 private static class SingletonInstance{ //静态属性 private static final Singleton INSTANCE=new Singleton(); } public static Singleton getInstance() { //该方法调用时,静态内部类加载,里面的静态属性才会赋值 return SingletonInstance.INSTANCE; } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
枚举
enum Singleton { //枚举常量 INSTANCE; //底层: public static final Singleton INSTANCE= new Singleton (); //方法 public void getInstance() { System.out.println("得到实例"); } } public class Main { public static void main(String[] args) { Singleton s1=Singleton.INSTANCE; Singleton s2=Singleton.INSTANCE; s1.getInstance(); s2.getInstance(); System.out.println(s1.hashCode()==s2.hashCode()); } }
优缺点
单例模式注意事项
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!