大家好,欢迎来到IT知识分享网。
一、『单件模式』定义
确保一个类只有一个实例,并提供一个全局访问点。
单件模式即单例模式。
使用场景很多,比如多个程序都要使用一个配置文件中的数据,而且要实现数据共享和交换。必须要将多个数据封装到一个对象中,而且多个程序操作的是同一个对象,也就是说必须保证这个配置文件对象的唯一性。
有两种方式实现:饿汉式和懒汉式。
二、使用
2.1 饿汉式
单件模式的急切实例化方式,上来就创建对象:
class Single {
//2,创建一个本类对象。 private static Single uniqueInstance = new Single(); //1,私有化构造函数。禁止程序创建该类的对象。 private Single() {
} //3,定义一个方法返回这个对象。该方法加上public,权限最大。 public static Single getInstance() {
return uniqueInstance; } } / * 演示 */ public class Demo {
public static void main(String[] args) {
// 调用getInstance方法获取Single的对象。 Single ss1 = Single.getInstance(); Single ss2 = Single.getInstance(); // ss1和ss2操作的是同个对象,因为地址相同 System.out.println(ss1 == ss2); } }
如果创建的这个单件对象一直没用到过,而且该对象也一直比较占用空间,那么饿汉式并不是很完美的解决方法。
2.2 懒汉式
单例的延迟实例化方式,用到才创建对象:
class Single {
//2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() {
} //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() {
if (uniqueInstance == null) uniqueInstance = new Single(); return uniqueInstance; } } / * 演示 */ public class Demo {
public static void main(String[] args) {
// 调用getInstance方法获取Single的对象。 Single ss1 = Single.getInstance(); Single ss2 = Single.getInstance(); // ss1和ss2操作的是同个对象,因为地址相同 System.out.println(ss1 == ss2); } }
2.3 小细节
(1)私有化构造函数是为了禁止其它程序创建该类的对象,保证只有该类内部才能创建该类的对象。
(2)想获取Single类的对象就需要调用getInstance方法。既然无法通过对象调用,那么只能用类名调用,所以getInstance方法必须是static。
(3)创建好对象后,因为uniqueInstance对象是静态的,所以通过Single.uniqueInstance这种方式是可以获取对象的,但不推荐,用方法访问是为了对对象可控,因此对象需加上private。
三、单件模式的多线程安全问题
对比饿汉式和懒汉式两种单件模式的实现,饿汉式没有多线程安全问题,但是懒汉式是有多线程安全问题的。
3.1 懒汉式分析一
初始的饿汉式实现:
class Single {
//2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() {
} //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() {
if (uniqueInstance == null) uniqueInstance = new Single(); return uniqueInstance; } }
问题:假设现在uniqueInstance对象还是null,然后有多个线程同时调用getInstance()方法想获得uniqueInstance对象,可能会出现多个线程都判断uniqueInstance为空,接着就重复new了对象,这里就出现多线程安全问题了。
3.2 懒汉式分析二
上面分析发现:并发访问会有安全隐患,所以加入同步机制解决安全问题。
class Single {
//2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() {
} //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() {
synchronized (Single.class) {
if (uniqueInstance == null) uniqueInstance = new Single(); } return uniqueInstance; } }
问题:只有第一次执行此方法时,才真正需要同步。换句话说,一旦创建好uniqueInstance对象,就不再需要同步这个方法了。之后每次调用这个方法,同步都是一种累赘。
3.3 懒汉式分析三
上面分析发现:同步的出现降低了效率。可以通过双重判断的方式,解决效率问题,减少判断锁的次数。
class Single {
//2,创建一个本类对象。 private volatile static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() {
} //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() {
if(uniqueInstance == null) {
synchronized (Single.class) {
if (uniqueInstance == null) uniqueInstance = new Single(); } } return uniqueInstance; } }
volatile关键词确保:uniqueInstance变量被初始化成Single实例时,多个线程正确地处理uniqueInstance变量。
参考
《HeadFirst设计模式》
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141949.html