单例模式-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等分布式协调工具去完成了

相关推荐
夜晚中的人海6 分钟前
【C++】智能指针介绍
android·java·c++
小蕾Java17 分钟前
Python详细安装教程(附PyCharm使用)
开发语言·python·pycharm
weixin_3077791323 分钟前
AWS云上ClickHouse数据仓库部署方案详解
开发语言·clickhouse·自动化·云计算·aws
weixin_3077791325 分钟前
使用AWS IAM和Python自动化权限策略分析与导出
开发语言·python·自动化·云计算·aws
正在走向自律26 分钟前
RSA加密从原理到实践:Java后端与Vue前端全栈案例解析
java·前端·vue.js·密钥管理·rsa加密·密钥对·aes+rsa
惜月_treasure31 分钟前
从零构建私域知识库问答机器人:Python 全栈实战(附完整源码)
开发语言·python·机器人
咯哦哦哦哦44 分钟前
关于QT 打印中文 乱码问题
java·数据库·qt
mark-puls1 小时前
Qt界面布局利器:QStackedWidget详细用法解析
开发语言·qt
爱读源码的大都督1 小时前
天下苦@NonNull久矣,JSpecify总算来了,Spring 7率先支持!
java·后端·架构
chennn121 小时前
c++相关学习
开发语言·c++·学习