设计模式(一):单例模式

一.单例模式的特点:

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

 

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

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

    在开始到结束的生命周期中只进行一次实例化。

 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+"\n");
 8             lazyinstance instance1 = lazyinstance.getInstance();
 9             System.out.println(instance1+"\n");
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 }
单线程下的懒汉式

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

设计模式(一):单例模式_第1张图片

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

设计模式(一):单例模式_第2张图片

 设计模式(一):单例模式_第3张图片

 

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

 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+"\n");
10         }).start();
11         //线程二
12         new Thread(()->{
13             lazyinstance instance1  = lazyinstance.getInstance();
14             System.out.println(instance1+"\n");
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 }

多线程下的懒汉式

设计模式(一):单例模式_第4张图片

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

    与此同时,对实例化进行加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+"\n");
10         }).start();
11         //线程二
12         new Thread(()->{
13             lazyinstance instance1  = lazyinstance.getInstance();
14             System.out.println(instance1+"\n");
15         }).start();
16         //线程三
17         new Thread(()->{
18             lazyinstance instance2  = lazyinstance.getInstance();
19             System.out.println(instance2+"\n");
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的加入

 

设计模式(一):单例模式_第5张图片

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

原因:

设计模式(一):单例模式_第6张图片

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

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

设计模式(一):单例模式_第7张图片

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

设计模式(一):单例模式_第8张图片

 

五.饿汉式Singleton:

在每次开始时便自动进行实例化,不需要调用便实例化成功。

设计模式(一):单例模式_第9张图片

     使用static 在类加载时便进行了实例化。;在多线程下相对更安全。

 1 package com.cllover.hunger;
 2 /*
 3 * 饿汉式单例模式
 4 * */
 5 public class hungerSingleton {
 6     public static void main(String[] args) {
 7 
 8         new Thread(()->{
 9             hungerInstance instance = hungerInstance.getInstance();
10             System.out.println(instance);
11         }).start();
12         new Thread(()->{
13             hungerInstance instance1 = hungerInstance.getInstance();
14             System.out.println(instance1);
15         }).start();
16     }
17 }
18 
19 class hungerInstance{
20 
21     private static hungerInstance instance = new hungerInstance();
22     private hungerInstance(){
23     }
24 
25     public static hungerInstance getInstance() {
26         return instance;
27     }
28 }
多线程下的饿汉式

  设计模式(一):单例模式_第10张图片

    在线程开始前进行实例化并设置有初值,两个线程同时开始后获取到相同的值

设计模式(一):单例模式_第11张图片

 

你可能感兴趣的:(设计模式(一):单例模式)