设计模式:单例模式

Posted cllover

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式:单例模式相关的知识,希望对你有一定的参考价值。

一.单例模式的特点:

    在单例模式的开始和结束中,这个过程只会实例化一个对象。

 

二.懒汉式的写法及特点:

    懒汉式顾名思义就是越懒越好,你不用我,我便不去实例化。只有在调用时,才会进行实例化操作。

技术图片
 1 package com.cllover.lazy;
 2 
 3 public class LazySingleton {
 4     public static void main(String[] args) {
 5 
 6             lazyinstance instance = lazyinstance.getInstance();
 7             System.out.println(instance+"
");
 8             lazyinstance instance1 = lazyinstance.getInstance();
 9             System.out.println(instance1+"
");
10 
11 
12     }
13 }
14 
15 
16 class lazyinstance{
17 
18     private static lazyinstance instance;
19 
20     private lazyinstance(){
21     }
22 
23     public  static lazyinstance getInstance() {
24         if (instance == null){
25           instance = new lazyinstance();
26         }
27         return instance;
28     }
29 }
单线程下的懒汉式

    在单线程下,由于第一次进行实例化在此前并没有提前进行实例化操作,所以符合条件进行实例化操作 

技术图片

    在实例化化得过程中进行了new空间 ,初始化和引用赋值等几个步骤。再进行第二次实例化时,由于第一次已经存在值,所以第二次条件不成立,直接返回第一次实例化结果,所以两次结果相等为true

技术图片

 技术图片

 

三.那么在多线程下是否安全那?

技术图片
 1 package com.cllover.lazy;
 2 
 3 public class LazySingleton {
 4 
 5     public static void main(String[] args) {
 6         //线程一
 7         new Thread(()->{
 8             lazyinstance instance  = lazyinstance.getInstance();
 9             System.out.println(instance+"
");
10         }).start();
11         //线程二
12         new Thread(()->{
13             lazyinstance instance1  = lazyinstance.getInstance();
14             System.out.println(instance1+"
");
15         }).start();
16     }
17 }
18 class lazyinstance{
19 
20     private static lazyinstance instance;
21 
22     private lazyinstance(){
23     }
24 
25     public  static lazyinstance getInstance() {
26 
27         if (instance == null){
28           instance = new lazyinstance();
29         }
30         return instance;
31     }
32 }

多线程下的懒汉式

技术图片

    很显然在多线程下,各自线程进行自己的实例化操作, 造成不安全的因素在里面,在进行相同的实例化操作下 并不相同,

    与此同时,对实例化进行加lock或者加 synchronized 进行加锁。

 

四.使用synchronized 同步锁

    synchronized能够解决在多线程的条件下,控制线程无法同时进行,进行同步堵塞。在这里定义了三个线程进行验证  

技术图片
 1 package com.cllover.lazy;
 2 
 3 public class LazySingleton {
 4 
 5     public static void main(String[] args) {
 6         //线程一
 7         new Thread(()->{
 8             lazyinstance instance  = lazyinstance.getInstance();
 9             System.out.println(instance+"
");
10         }).start();
11         //线程二
12         new Thread(()->{
13             lazyinstance instance1  = lazyinstance.getInstance();
14             System.out.println(instance1+"
");
15         }).start();
16         //线程三
17         new Thread(()->{
18             lazyinstance instance2  = lazyinstance.getInstance();
19             System.out.println(instance2+"
");
20         }).start();
21     }
22 }
23 class lazyinstance{
24 
25     private static lazyinstance instance;
26 
27     private lazyinstance(){
28     }
29 
30     public  static lazyinstance getInstance() {
31 
32         if (instance == null){
33             //同步堵塞
34             synchronized (lazyinstance.class){
35                 //是否进行过实例化
36                 if (instance == null){
37                     instance = new lazyinstance();
38                 }
39             }
40         }
41         return instance;
42     }
43 }
synchronized的加入

 

技术图片

   在进行了加锁之后,结果相同。

原因:

技术图片

     在三个线程同时运行中,由于synchronized的作用并没有同时进行实例化操作。

    先有“线程一”就行实例化,由于是第一次实例化所以条件符合,new了一个新的实例。第一个线程结束后,第二个线程由“线程三”开始进行检测是否已经存在instance的值。由于“线程一”的实例化,进行了引用赋值,所以在“线程二”中可以直接获取值。并在检测中显示不符合条件,存在这个值。并带回这个结果。

技术图片

     最后进行“线程一”由于存在值,所以不用new新的实例,并带回结果。所以再加入锁的情况下懒汉式多线程相对较为安全。

技术图片

 

 

五.饿汉式:

 

以上是关于设计模式:单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块

设计模式之单例模式

设计模式之单例模式