单例模式
Posted Jemb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
什么单例模式?
单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。其实,GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
为什么要使用单例模式?
在应用系统开发中,我们常常有以下需求:
- 在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象
- 在整个程序空间使用全局变量,共享资源
- 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
因为Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。
怎么实现模式?
1.饿汉式。
1 public class Person { 2 //用static修饰因为方法是静态的需要调用,final是因为变量只会被赋值一次,保证单例 3 public static final Person person = new Person(); 4 private String name; 5 6 public String getName() { 7 return name; 8 } 9 10 public void setName(String name) { 11 this.name = name; 12 } 13 14 //构造函数私有化保证不能实例化对象 15 private Person() { 16 } 17 18 //提供一个全局的静态方法 19 public static Person getPerson() { 20 return person; 21 } 22 }
2.懒汉式。
---多线程环境下不能保证单例唯一
1 public class Person2 { 2 private String name; 3 private static Person2 person; 4 5 public String getName() { 6 return name; 7 } 8 9 public void setName(String name) { 10 this.name = name; 11 } 12 13 //构造函数私有化 14 private Person2() { 15 } 16 17 //提供一个全局的静态方法 18 public static Person2 getPerson() { 19 if(person == null) { //*如果两个线程都在此处进入,就会创建两个对象,保证不了单例 20 person = new Person2(); 21 } 22 return person; 23 } 24 }
---使用同步方法,保证单例唯一,但是锁住了整个方法,而我们只需要锁住“new 对象()”这段,所以会影响到性能
1 public class Person3 { 2 private String name; 3 private static Person3 person; 4 5 public String getName() { 6 return name; 7 } 8 9 public void setName(String name) { 10 this.name = name; 11 } 12 13 //构造函数私有化 14 private Person3() { 15 } 16 17 //提供一个全局的静态方法,使用同步方法 18 public static synchronized Person3 getPerson() { 19 if(person == null) { 20 person = new Person3(); 21 } 22 return person; 23 } 24 }
3.双重检查。
为什么要双重检查?
当两个线程都一起通过第一个“person=null”的时候,线程1执行同步代码块的代码,创建对象, 但是因为线程2也已经通过第一个“person=null”判断条件,如果没有再加一层判断,也会创建另一个对象,造成非单例。这时需要在同步代码块加一层判断,线程1执行完对象的创建,这是person就不为空了,以后的线程通不过第二个if条件,自然也就保证了单例。
public class Person4 { private String name; private static Person4 person; public String getName() { return name; } public void setName(String name) { this.name = name; } //构造函数私有化 private Person4() { } //提供一个全局的静态方法 public static Person4 getPerson() { if(person == null) { synchronized (Person4.class) { if(person == null) { person = new Person4(); } } } return person; } }
主函数:
public class MainClass { public static void main(String[] args) { //饿汉模式 Person per1 = Person.getPerson(); Person per2 = Person.getPerson(); per1.setName("rr"); per2.setName("meimei"); System.out.println(per1.getName()); System.out.println(per2.getName()); System.out.println("-------------------"); //懒汉模式1 Person2 per3 = Person2.getPerson(); Person2 per4 = Person2.getPerson(); per4.setName("rr"); per4.setName("meimei"); System.out.println(per3.getName()); System.out.println(per4.getName()); System.out.println("-------------------"); //懒汉模式2 Person3 per5 = Person3.getPerson(); Person3 per6 = Person3.getPerson(); per5.setName("rr"); per6.setName("meimei"); System.out.println(per5.getName()); System.out.println(per6.getName()); System.out.println("-------------------"); //双重判断 Person4 per7 = Person4.getPerson(); Person4 per8 = Person4.getPerson(); per7.setName("rr"); per8.setName("meimei"); System.out.println(per7.getName()); System.out.println(per8.getName()); System.out.println("-------------------"); } }
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章