单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象,一个最好的办法就是,让类自身负责保存他的唯一实例。这个类可以保证没有其它实例可以被创建,并且它可以提供一个访问该实例的方法。
单例模式又可以分为---饿汉式和懒汉式。
懒汉式:
1 //单例模式---懒汉式 第一次被使用时,才会被实例化 2 public class Single { 3 private static Single instance; 4 5 //构造方法让其private,这就杜丝勒外界利用new创建此类实例的可能 6 private Single(){} 7 8 //此方法是获得本类实例的唯一全局访问点。返回该类的实例 9 public static Single getInstance(){ 10 //若实例不存在,则new 一个新实例,否则返回已有的实例 11 if(instance==null){ 12 instance = new Single(); 13 } 14 return instance; 15 } 16 }
测试类:
1 public class TestClient { 2 public static void main(String[] args) { 3 Single s1 = Single.getInstance(); 4 Single s2 = Single.getInstance(); 5 //比较两次实例化后对象的结果是实例相同 6 if(s1==s2){ 7 System.out.println("两个对象是相同的实例"); 8 }else{ 9 System.out.println("不同"); 10 } 11 //打印结果:两个对象是相同的实例 12 } 13 }
饿汉式:
1 //单例模式---饿汉式 在自己被加载时就将自己实例化 2 public class Single2 { 3 private static Single2 instance = new Single2(); 4 5 //构造方法让其private,这就杜绝外界利用new创建此类实例的可能 6 private Single2(){} 7 8 //此方法是获得本类实例的唯一全局访问点,返回该类的实例。静态方法 9 public static Single2 getInstance(){ 10 return instance; 11 } 12 }
测试类:
1 public class TestClient2 { 2 public static void main(String[] args) { 3 Single2 s1 = Single2.getInstance(); 4 Single2 s2 = Single2.getInstance(); 5 //比较两次实例化后对象的结果是实例相同 6 if(s1==s2){ 7 System.out.println("两个对象是相同的实例"); 8 }else{ 9 System.out.println("不同"); 10 } 11 //打印结果:两个对象是相同的实例 12 } 13 }
=================================================多线程下的单例模式====================================================>>>>>
多线程下的单例模式:
1 //多线程时的单例 2 public class Singleton { 3 private static Singleton instance; 4 private static Object syncRoot = new Object(); 5 6 //让构造方法私有,这就杜丝勒外界利用new创建此类实例的可能。不让外界通过new创建对象 7 private Singleton(){} 8 9 //静态方法 10 public static Singleton getInstance(){ 11 //先判断实例是否存在,不存在再加锁处理 12 if(instance==null){ 13 synchronized (syncRoot) { 14 if(instance==null){ 15 instance = new Singleton(); 16 } 17 } 18 } 19 return instance; 20 } 21 /** 22 * 为什么在外面已经判断了instance实例是否存在,还要在synchronized里面做一次实例是否存在的判断呢? 23 * 对于instance存在的情况,就直接返回,这没有问题。 24 * 当instance为null并且同时又两个线程调用getInstance()方法时,他们都可以通过第一重instance==null的判断。然后由于synchronized机制, 25 * 这两个线程则只有一个进入,另一个在外排队等候,必须要其中的一个进入并出来后,另一个才能进入。 26 * 而此时如果没有了第二重的instance是否为null的判断,则第一个线程创建了实例,而第二个线程还是可以继续再创建新的实例,这个就没有达到单例的目的了。 27 */ 28 }