单例模式-java实现

介绍

单例模式的意图:保证某个类在系统中有且仅有一个实例。

我们可以看到下面的类图:一般的单例的实现,是属性中保持着一个自己的私有静态实例引用,还有一个私有的构造方法,然后再开放一个静态的获取实例的方法给外界获取实例对象。

代码实现

在java中有两种实现的方法

  • 饿汉式:在类加载的时候就创建好实例
  • 懒汉式:在请求实例时才创建实例

饿汉式

在类加载的时候就创建好实例

java 复制代码
public class TestObj {
    private static TestObj testObj=new TestObj();
    //构造方法私有化
    private TestObj(){

    }
    //提供一个外界获取单实例的静态方法
    public static  TestObj getTestObj(){
        return testObj;
    }
}

懒汉式

由于java是多线程的,很有可能多个线程同时进入,导致创建多个实例,于是我们要使用锁机制来让线程之间互斥访问

java 复制代码
public class TestObj2 {
    //初始,维护一个静态的空引用
    private static TestObj2 testObj2=null;
    //私有的构造方法
    private TestObj2(){

    }
    //提供给外界获取单实例的静态方法
    public static TestObj2 getTestObj2(){
        //在这里,由于java是多线程的,很有可能多个线程同时进入,导致创建多个实例,于是我们要使用锁机制来让线程之间互斥访问
        //多线程同时判断,如果不为null,直接返回
        if (testObj2!=null){
            return testObj2;
        }
        //使用同步代码块进行线程互斥访问
        synchronized (Object.class){
            //其他线程进入以后,如果已经创建好了对象,则直接返回
            if (testObj2!=null){
                return testObj2;
            }
            else {
                //初始化单实例
                testObj2=new TestObj2();
            }

        }
        return testObj2;

    }
}

我们这里测试一下:

创建三个线程同时去获取实例,看输出的地址是否一样

java 复制代码
//创建一个runable接口
class DoTask implements Runnable{
    @Override
    public void run() {
        //获取实例对象并输出
        TestObj2 testObj2 = TestObj2.getTestObj2();
        System.out.println(testObj2);
    }
}

class Main{
    public static void main(String[] args) {
        Runnable runnable=new DoTask();
        //创建多个线程去获取实例
        Thread thread1=new Thread(runnable);
        Thread thread2=new Thread(runnable);
        Thread thread3=new Thread(runnable);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果:

可以看到输出的三个地址都是相同的,因此我们上面的懒汉式代码是完全可行的,这里仅仅讨论单服务器的情况,如果是分布式系统中的单实例,就要考虑使用分布式锁,或者redis,zookeeper等分布式协调工具去完成了

相关推荐
天之涯上上几秒前
JAVA开发 在 Spring Boot 中集成 Swagger
java·开发语言·spring boot
2402_857583492 分钟前
“协同过滤技术实战”:网上书城系统的设计与实现
java·开发语言·vue.js·科技·mfc
白宇横流学长2 分钟前
基于SpringBoot的停车场管理系统设计与实现【源码+文档+部署讲解】
java·spring boot·后端
APP 肖提莫6 分钟前
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
java·前端·算法
kirito学长-Java7 分钟前
springboot/ssm太原学院商铺管理系统Java代码编写web在线购物商城
java·spring boot·后端
爱学习的白杨树8 分钟前
MyBatis的一级、二级缓存
java·开发语言·spring
OTWOL14 分钟前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
问道飞鱼17 分钟前
【前端知识】强大的js动画组件anime.js
开发语言·前端·javascript·anime.js
拓端研究室18 分钟前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
Code成立19 分钟前
《Java核心技术I》Swing的网格包布局
java·开发语言·swing