标签:system hashcode null 简单 auto 有一个 return run cep
单例模式:只有一个实例的设计模式。
单例模式有三点要求
* 构造方法私有化(保证外部不能直接构造)
* 提供一个静态私有属性指向实例
* 提供一个公有的静态方法提供实例
简单单例演示
1 /** 2 * 懒汉式单例模式演示 3 * @author 67471 4 * 5 */ 6 public class Singeton { 7 private static Singeton singeton; 8 private Singeton(){} 9 private static Singeton getSingeton(){ 10 if (singeton==null) { 11 singeton =new Singeton(); 12 return singeton; 13 } 14 return singeton; 15 } 16 }
测试
public static void main(String[] args) { Singeton instance = Singeton.getSingeton(); Singeton instance2 = Singeton.getSingeton(); System.out.println(instance==instance2); }
结果:true
这里还有一个问题就是多线程下就有问题了。什么问题呢?请看下面代码
演示
1 package thead; 2 /** 3 * 多线程情况下的单利模式 4 * @author 67471 5 * 6 */ 7 public class Singeton implements Runnable{ 8 private static Singeton singeton; 9 private Singeton(){} 10 private static Singeton getSingeton() throws InterruptedException{ 11 if (singeton==null) { 12 Thread.sleep(200); 13 singeton =new Singeton(); 14 return singeton; 15 } 16 return singeton; 17 } 18 @Override 19 public void run() { 20 try { 21 System.out.println(getSingeton().hashCode()); 22 } catch (InterruptedException e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } 26 } 27 28 }
测试
public static void main(String[] args) { Thread[] thrs = new Thread[10]; for (int i = 0; i < thrs.length; i++) { thrs[i] = new Thread(new Singeton3()); } for (int i = 0; i < thrs.length; i++) { thrs[i].start(); } }
结果:
935563448 1320194849 1820973978 1202453864 935563448 139607202 1326101490 935563448 935563448 763347431
产生这种结果的原因是每个线程进去后判断singeton为null,都创建了一个实例。拿到的不是同一个实例,那就不是单利模式。
解决这个问题的思路:用synchronized关键字解决,问题是synchronized加在哪?加在getSingeton()方法上会解决这个问题,但是效率太低,浪费系统资源,如果属性singeton不为null,将其他线程挡在
外面不合适,应该在创建对象时同步。看下面演示
还是上面代码只改变getSingeton方法
1 private static Singeton3 getSingeton() throws InterruptedException{ 2 if (singeton==null) { 3 Thread.sleep(200); 4 synchronized(new Object()){ 5 singeton =new Singeton(); 6 return singeton; 7 } 8 } 9 return singeton; 10 }
测试结果
139607202 1175759956 1414135615 512965639 763347431 763347431 1820973978 1320194849 1202453864 139607202
这里就MMP了,想了想漏了一个情况,多个线程同时进来时,此时singeton=null。都进入if循环内,都准备进入同步代码块内,如果不再次判断还是会创建多个实例
应该在同步代码块中再判断下是否为null,是null再创建,如下;
1 private static Singeton3 getSingeton() throws InterruptedException{ 2 if (singeton==null) { 3 Thread.sleep(200); 4 synchronized(new Object()){ 5 6 if (singeton==null) { 7 8 singeton =new Singeton(); 9 return singeton; 10 } 11 } 12 } 13 return singeton; 14 }
测试结果
139607202 139607202 139607202 139607202 139607202 139607202 139607202 139607202 139607202 139607202
总结:这就是单利模式下的双重检测,懂了之后抑郁症也好了。
标签:system hashcode null 简单 auto 有一个 return run cep
原文地址:https://www.cnblogs.com/xiejiangping/p/9349577.html