JAVA之单例模式

//记录为自己学习过程

先说说单例模式: // 后面有一个自己写的小程序例子

单例   别名单体/单件/单态    Singleton

单例就是希望某一个类仅有一个实例的时候,采用的一种程序设计模式.

自然首先会遇到这样1个问题.

为什么会存在这样一个模式?

单例贵在实例的唯一性.所以当需要某个实例对象有且仅有一个的时候,我们需要用单例.比较常引用的例子有:用来计算网络在线人数.我们需要一个全局的对象来负责计数,但是又要配合一定的数据和方法来保证他的结构性,这个计数器又得唯一(如果不唯一,多个计数器协同作用容易导致计数不准确),就需要用到单例模式了.

//贵在唯一性以减少程序逻辑错误,而非全局

简单来说单例模式有两种.

懒汉式

饿汉式

(还有一种双重锁形式 其实也是配合了上面的懒汉式模式)

给出两种模式的简单代码先 //这个这都有 

public class SingletonClass{
    private static SingletonClass instance=null;
    public static synchronized SingletonClass getInstance(){	
        if(instance==null){
               instance=new SingletonClass();
        }
        return instance;
    }
    private SingletonClass(){
    }
}

解析:

为何需要    private static SingletonClass instance=null;     ??

答:其实可以不要,但是要了会快一些,这是缓存的概念.先缓存这样一个数据在内存里,如果有,就直接用,如果没有,再去找.

再去找,有就直接用了,没有再想办法去其他地方找. //像cache

其他解析:

//由于构造函数的私有,外界无法创建实例,又由于内部的判断导致仅存在一个实例,很好理解

// 函数加了 synchronized 关键字之后,方法被锁定.从而同一时刻最多只有一个线程执行这段代码.这样可以从线程角度再次确保单例的唯一性

// 否则如果A程序到了return那里马上要把一个对象放出来了(还没放),B程序又刚过instance的检查,这时候instance==null 所以又new出一个对象,

// 结果就会产生两个实例

// 获取实例的函数需要 public 属性 供外界访问 而且 instance和getInstance要有 static 属性

// getInstance是为了作为类方法才能外界才能"调得起来",

// instance静态是因为 静态方法只能调用静态变量

饿汉式:

public class Singleton{
    //在自己内部定义自己的一个实例,只供内部调用
    private static final Singleton instance = new Singleton();
    private Singleton(){
        //do something
    }
    //这里提供了一个供外部访问本class的静态方法,可以直接访问
    public static Singleton getInstance(){
        return instance;
    }
}

其实就是在这个类建立的时候,直接建立一个实例对象.这就无所谓线程不安全了! 看上去也很简单

下面说一下双重锁的形式:

public class Singleton{
    private static volatile Singleton instance=null;
    private Singleton(){
        //do something
    }
    public static  Singleton getInstance(){
        if(instance==null){
            synchronized(SingletonClass.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
     }
}

这个还是值得解释一下的. 我们主要拿他来和之前第一种说的懒汉式做对比

这里使用 synchronized 的时机变了,原本用在进入 getInstance的时候就加锁,现在用在了 第二层 if 之后

我有这样2个问题

1.为什么要改变用 synchronized (同步)的时机

2.为什么要两重 IF

答1

同步是有代价的,一方面自身同步需要时间,其次会影响其他进程.如果 synchronized在 getnstance() 上,那么每一次获得这个单例对象,都需要同步,浪费了资源.现在改到

当instance不存在之后再同步,可以避免反复同步又可以防止产生多个单例实例.

答2

那为何还需要下一个if呢?原因是除了 synchronized 之外的代码段之后,线程仍然是可能产生冲突的.比如某个线程A 进入了第二个if 正要开始new 有另外一个线程进入第一个判断 instance 为NULL进入了同步,那我先等着,等你A new完,我还是进去new了..一样会导致创建了多个实例


接下来贴一个我自己写的用于判断数字奇偶的单例小程序= = 没用单例的必要..就是用用

/****************************************
    Filename:   Singleton.java
    CreateTime: 2017年03月13日21:07:14
****************************************/
import java.util.*;
class J_Singleton{
    private static  J_Singleton m_object;

    private J_Singleton(){};          //私有防止调用
    public static J_Singleton mb_getObject(){
        if(m_object==null){
            synchronized(J_Singleton.class){
                if(m_object==null){
                    m_object=new J_Singleton();
                }

            }
        }
        return m_object;
    }
    public void judgeOddorEven(int num){
        if(num%2==0){
            System.out.println("EVEN");
        }else{
            System.out.println("ODD");
        }
    }
}

public class Singleton{
    public static void main(String args[]){
        J_Singleton myST=J_Singleton.mb_getObject();

        Scanner sc=new Scanner(System.in);
        int num;
        num=sc.nextInt();
        while(num!=0){
            myST.judgeOddorEven(num);
            num=sc.nextInt();
        }
        System.out.println("EVEN");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值