zoukankan      html  css  js  c++  java
  • 设计模式(一):单例模式

    一.单例模式的特点:

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

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

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

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

     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新的实例,并带回结果。所以再加入锁的情况下懒汉式多线程相对较为安全。

    五.饿汉式Singleton:

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

         使用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 }
    多线程下的饿汉式

      

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

  • 相关阅读:
    Android Layout XML属性
    linux]ubuntu挂载U盘
    Android之NDK开发
    Android 创建永不Kill的Service
    如何编写可移植的c/c++代码
    Android写日志文件类
    Android Activity去除标题栏和状态栏
    linux .bash_profile和.bashrc的什么区别
    ListView.setOnItemClickListener、setOnCreateContextMenuListener无效 为什么
    WCF 第四章 绑定 使用队列技术进行通信
  • 原文地址:https://www.cnblogs.com/CllOVER/p/13303009.html
Copyright © 2011-2022 走看看