码迷,mamicode.com
首页 > 其他好文 > 详细

单例模式

时间:2018-07-22 12:58:00      阅读:161      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!