《C++新经典设计模式》之第7章 单例模式

《C++新经典设计模式》之第7章 单例模式

        • 单例模式.cpp

单例模式.cpp
#include <iostream>
#include <memory>
#include <mutex>
#include <vector>
#include <atomic>
using namespace std;

// 懒汉式,未释放
namespace ns1
{
    class GameConfig
    {
        static GameConfig *m_instance1; // 指向本类对象的指针
        // static mutex m_mutex;
        // static shared_ptr<GameConfig> GameConfig::m_instance3;

    private:
        GameConfig(){};
        GameConfig(const GameConfig &tmpobj);
        GameConfig &operator=(const GameConfig &tmpobj);
        ~GameConfig(){};

    public:
        static GameConfig *getInstance1()
        {
            // lock_guard<mutex> l(m_mutex);
            if (m_instance1 == nullptr)
                m_instance1 = new GameConfig();
            return m_instance1;
        }
        static GameConfig *getInstance2()
        {
            static GameConfig m_instance2;
            return &m_instance2;
        }
        /*
        static shared_ptr<GameConfig> getInstance3()
        {
            if (m_instance3 == nullptr)
                m_instance3 = make_shared<GameConfig>();
            return m_instance3;
        }
        */
        /*
        static shared_ptr<GameConfig> getInstance4()
        {
            static shared_ptr<GameConfig> m_instance4(new GameConfig());
            return m_instance4;
        }
        */
    };
    GameConfig *GameConfig::m_instance1 = nullptr;
    // mutex GameConfig::m_mutex;
    // shared_ptr<GameConfig> GameConfig::m_instance3 = nullptr;
}

// 懒汉式,嵌套类释放
namespace ns2
{
    class GameConfig
    {
        static GameConfig *m_instance;
        // static mutex m_mutex;
    private:
        GameConfig(){};
        GameConfig(const GameConfig &tmpobj);
        GameConfig &operator=(const GameConfig &tmpobj);
        ~GameConfig(){};

    public:
        static GameConfig *getInstance()
        {
            // lock_guard<mutex> gcguard(m_mutex);
            if (m_instance == nullptr)
            {
                // 这里再加锁
                // lock_guard<mutex> gcguard(m_mutex);
                // if (m_instance == nullptr)
                //{
                m_instance = new GameConfig();
                static Garbo garboobj;
                //}
            }
            return m_instance;
        }

    public:
        static void freeInstance() // 要手工调用才能释放内存
        {
            if (GameConfig::m_instance != nullptr)
            {
                delete GameConfig::m_instance;
                GameConfig::m_instance = nullptr;
            }
        }

    private:
        class Garbo // 手工释放单件类对象引入的GameConfig类中的嵌套类(垃圾回收)
        {
        public:
            ~Garbo() { GameConfig::freeInstance(); }
        };
    };
    GameConfig *GameConfig::m_instance = nullptr;
    // mutex GameConfig::m_mutex;
}

// 懒汉式,加锁+嵌套类释放
namespace ns3
{
    class GameConfig
    {
        static atomic<GameConfig *> m_instance;
        static mutex m_mutex;

    private:
        GameConfig(){};
        GameConfig(const GameConfig &tmpobj);
        GameConfig &operator=(const GameConfig &tmpobj);
        ~GameConfig(){};

    public:
        static GameConfig *getInstance()
        {
            GameConfig *tmp = m_instance.load(memory_order_relaxed);
            atomic_thread_fence(memory_order_acquire);
            if (tmp == nullptr)
            {
                lock_guard<mutex> lock(m_mutex);
                tmp = m_instance.load(memory_order_relaxed);
                if (tmp == nullptr)
                {
                    tmp = new GameConfig();
                    static Garbo garboobj;
                    atomic_thread_fence(memory_order_release);
                    m_instance.store(tmp, memory_order_relaxed);
                }
            }
            return tmp;
        }

    private:
        class Garbo // 手工释放单件类对象引入的GameConfig类中的嵌套类(垃圾回收)
        {
        public:
            ~Garbo()
            {
                if (GameConfig::m_instance != nullptr)
                {
                    delete GameConfig::m_instance;
                    GameConfig::m_instance = nullptr;
                }
            }
        };
    };
    atomic<GameConfig *> GameConfig::m_instance;
    mutex GameConfig::m_mutex;
}

// 饿汉式,嵌套类释放
namespace ns4
{
    class GameConfig
    {
        static GameConfig *m_instance;

    private:
        GameConfig(){};
        GameConfig(const GameConfig &tmpobj);
        GameConfig &operator=(const GameConfig &tmpobj);
        ~GameConfig(){};

    public:
        static GameConfig *getInstance() { return m_instance; }

    private:
        class Garbo // 手工释放单件类对象引入的GameConfig类中的嵌套类(垃圾回收)
        {
        public:
            ~Garbo()
            {
                if (GameConfig::m_instance != nullptr)
                {
                    delete GameConfig::m_instance;
                    GameConfig::m_instance = nullptr;
                }
            }
        };

    private:
        static Garbo garboobj;
    };
    GameConfig *GameConfig::m_instance = new GameConfig(); // 趁静态成员变量定义的时机直接初始化是被允许的,即便GameConfig构造函数用private修饰
    GameConfig::Garbo GameConfig::garboobj;
}

// 饿汉式
namespace ns5
{
    class GameConfig2
    {
        static GameConfig2 m_instance;

    private:
        GameConfig2(){};
        GameConfig2(const GameConfig2 &tmpobj);
        GameConfig2 &operator=(const GameConfig2 &tmpobj);
        ~GameConfig2(){};

    public:
        static GameConfig2 *getInstance() { return &m_instance; }
    };
    GameConfig2 GameConfig2::m_instance;

    class GameConfig
    {
    private:
        GameConfig(){};
        GameConfig(const GameConfig &tmpobj);
        GameConfig &operator=(const GameConfig &tmpobj);
        ~GameConfig(){};

    public:
        static GameConfig &getInstance()
        {
            static GameConfig instance;
            return instance;
        }
    };

    int myfunc()
    {
        static int stcs = 100; // 不需要调用myfunc函数,stcs就已经等于100了
        stcs += 180;
        return stcs;
    }
}

// 饿汉式
namespace ns111
{
    // 饿汉模式
    class CSingleton
    {
        CSingleton() {}
        ~CSingleton() {}

    public:
        static CSingleton *GetInstance()
        {
            static CSingleton instance;
            return &instance;
        }
    };

    // 饿汉模式2
    class CSingleton2
    {
        static CSingleton2 *instance;
        CSingleton2() {}
        ~CSingleton2() {}

    public:
        static CSingleton2 *GetInstance()
        {
            return instance;
        }
    };
    CSingleton2 *CSingleton2::instance = new CSingleton2();

    // 饿汉模式3,智能指针
    class CSingleton3
    {
        static shared_ptr<CSingleton3> instance;
        CSingleton3() {}
        ~CSingleton3() {}

    public:
        static shared_ptr<CSingleton3> GetInstance()
        {
            return instance;
        }
        static void destoryInstance(CSingleton3 *x)
        {
            delete x;
        }
    };
    shared_ptr<CSingleton3> CSingleton3::instance(new CSingleton3(), destoryInstance);

    // 饿汉模式4,静态嵌套类
    class CSingleton4
    {
        static CSingleton4 *instance;
        class Deleter
        {
        public:
            ~Deleter()
            {
                if (instance != nullptr)
                {
                    delete instance;
                    instance = nullptr;
                }
            }
        };
        static Deleter m_deleter;

        CSingleton4() {}
        ~CSingleton4() {}

    public:
        static CSingleton4 *GetInstance() { return instance; }
    };
    CSingleton4 *CSingleton4::instance = new CSingleton4();
    CSingleton4::Deleter CSingleton4::m_deleter;
}

namespace ns222
{
    // 懒汉模式1
    class Singleton1
    {
        static Singleton1 *instance;

        Singleton1() {}
        ~Singleton1() {}

    public:
        static Singleton1 *getInstance()
        {
            if (instance == nullptr)
                instance = new Singleton1();
            return instance;
        }
    };
    Singleton1 *Singleton1::instance = nullptr;

    // 懒汉模式2
    class Singleton2
    {
        static Singleton2 *m_instance;
        static mutex mtx;
        Singleton2() {}
        ~Singleton2() {}

    public:
        Singleton2(const Singleton2 &) = delete;
        Singleton2 &operator=(const Singleton2 &) = delete;

    public:
        static Singleton2 *getInstance()
        {
            if (NULL == m_instance)
            {
                unique_lock<mutex> lock(mtx);
                if (NULL == m_instance)
                    m_instance = new Singleton2();
            }
            return m_instance;
        }
    };
    Singleton2 *Singleton2::m_instance = nullptr;
    mutex Singleton2::mtx;

    // 懒汉模式3,智能指针
    class Singleton3
    {
        static shared_ptr<Singleton3> m_instance;
        static mutex mtx;
        Singleton3() {}
        ~Singleton3() {}

    public:
        Singleton3(const Singleton3 &) = delete;
        Singleton3(Singleton3 &&) = delete;
        Singleton3 &operator=(const Singleton3 &) = delete;
        Singleton3 &operator=(Singleton3 &&) = delete;

    public:
        static void destoryInstance(Singleton3 *x) { delete x; }

        static shared_ptr<Singleton3> getInstance()
        {
            if (NULL == m_instance)
            {
                lock_guard<mutex> lock(mtx);
                if (NULL == m_instance)
                    m_instance.reset(new Singleton3(), destoryInstance);
            }
            return m_instance;
        }
    };
    shared_ptr<Singleton3> Singleton3::m_instance = nullptr;
    mutex Singleton3::mtx;

    // 懒汉模式4,静态嵌套类
    class Singleton4
    {
        static Singleton4 *m_instance;
        static mutex mtx;
        Singleton4() {}
        ~Singleton4() {}

        class Deleter
        {
        public:
            ~Deleter()
            {
                if (m_instance != nullptr)
                {
                    delete m_instance;
                    m_instance = nullptr;
                }
            }
        };
        static Deleter m_deleter;

    public:
        Singleton4(const Singleton4 &) = delete;
        Singleton4 &operator=(const Singleton4 &) = delete;

    public:
        static Singleton4 *getInstance()
        {
            if (NULL == m_instance)
            {
                lock_guard<mutex> lock(mtx);
                if (NULL == m_instance)
                    m_instance = new Singleton4();
            }
            return m_instance;
        }
    };
    Singleton4 *Singleton4::m_instance = nullptr;
    mutex Singleton4::mtx;
    Singleton4::Deleter Singleton4::m_deleter;

    // 懒汉模式5
    class Singleton5
    {
        static atomic<Singleton5 *> m_instance;
        static mutex mtx;
        Singleton5() {}
        ~Singleton5() {}

    public:
        Singleton5(const Singleton5 &) = delete;
        Singleton5 &operator=(const Singleton5 &) = delete;

    public:
        static Singleton5 *getInstance()
        {
            Singleton5 *p = m_instance;
            if (p == nullptr)
            {
                lock_guard<mutex> ll{mtx};
                if ((p = m_instance) == nullptr)
                    m_instance = p = new Singleton5();
            }
            return m_instance;
        }
    };
    atomic<Singleton5 *> Singleton5::m_instance{nullptr};
    mutex Singleton5::mtx;
}

//  加锁的懒汉式
namespace ns2_1
{
    class SingleInstance
    {
    private:
        static SingleInstance *m_SingleInstance;
        static mutex m_Mutex;

    private:
        SingleInstance() {}
        ~SingleInstance() {}

        SingleInstance(const SingleInstance &signal) {}
        const SingleInstance &operator=(const SingleInstance &signal) {}

    public:
        static SingleInstance *GetInstance()
        {
            if (m_SingleInstance == nullptr)
            {
                unique_lock<mutex> lock(m_Mutex); // 加锁
                if (m_SingleInstance == nullptr)
                {
                    volatile auto temp = new (nothrow) SingleInstance();
                    m_SingleInstance = temp;
                }
            }
            return m_SingleInstance;
        }

        static void deleteInstance()
        {
            unique_lock<mutex> lock(m_Mutex); // 加锁
            if (m_SingleInstance)
            {
                delete m_SingleInstance;
                m_SingleInstance = nullptr;
            }
        }
        void Print() { cout << "实例内存地址: " << this << endl; }
    };
    SingleInstance *SingleInstance::m_SingleInstance = nullptr;
    mutex SingleInstance::m_Mutex;
}

namespace ns2_2
{
    class Singleton
    {
        static shared_ptr<Singleton> singleton;
        static mutex singletonMutex;

    public:
        static shared_ptr<Singleton> getSingleton()
        {
            if (singleton == nullptr)
            {
                unique_lock<mutex> lock(singletonMutex);
                if (singleton == nullptr)
                    singleton.reset(new Singleton());
            }
            return singleton;
        }

        void print() { cout << "Hello World." << endl; }
        ~Singleton() { cout << __PRETTY_FUNCTION__ << endl; }

    private:
        Singleton() { cout << __PRETTY_FUNCTION__ << endl; }
    };
    shared_ptr<Singleton> Singleton::singleton = nullptr;
    mutex Singleton::singletonMutex;
}

namespace ns2_3
{
    class Singleton
    {
        static shared_ptr<Singleton> singleton;
        static once_flag singletonFlag;

    private:
        Singleton() {}

        // public:
        //     ~Singleton() {}

    public:
        void print() { cout << "Hello World." << endl; }

    public:
        static shared_ptr<Singleton> getSingleton()
        {
            call_once(singletonFlag, [&]
                      { singleton.reset(new Singleton()); });
            return singleton;
        }
    };

    shared_ptr<Singleton> Singleton::singleton = nullptr;
    once_flag Singleton::singletonFlag;
}

// 模板实现
namespace ns2_4
{
    template <typename T>
    shared_ptr<T> getInstance()
    {
        static shared_ptr<T> instance(new T());
        return instance;
    }

    class TestClass
    {
    public:
        TestClass() { cout << "TestClass constructed!" << endl; }
        void print() { cout << "TestClass Address: " << this << endl; }
    };
}

namespace ns22222
{
    class Single
    {
    private:
        Single() {}
        //~Single() {}
        static shared_ptr<Single> instance;
        Single(const Single &);
        Single &operator=(const Single &);

    public:
        static Single &getInstance()
        {
            if (instance == nullptr)
                instance.reset(new Single());
            return *instance;
        }
    };
    shared_ptr<Single> Single::instance = nullptr;

    class SingleObject
    {
        static shared_ptr<SingleObject> instance;
        SingleObject() {}
        // public:
        //~SingleObject() {}
    public:
        static shared_ptr<SingleObject> getInstance() { return instance; }
        void showMessage() { cout << "Hello World!" << endl; }
    };
    shared_ptr<SingleObject> SingleObject::instance(new SingleObject());
}

int main()
{
#if 0
    using namespace ns1;
    GameConfig *g_gc1 = GameConfig::getInstance1();
    GameConfig *g_gc2 = GameConfig::getInstance2();
#endif

#if 0
    using namespace ns2;
    GameConfig *g_gc = GameConfig::getInstance();
    // g_gc->freeInstance(); // 手工释放内存演示
#endif

#if 0
    using namespace ns3;
    GameConfig *g_gc = GameConfig::getInstance();
    GameConfig *g_gc2 = GameConfig::getInstance();
#endif

#if 0
    using namespace ns4;
    GameConfig *g_gc = GameConfig::getInstance();
    GameConfig *g_gc2 = GameConfig::getInstance();
#endif

#if 0
    using namespace ns5;
    GameConfig2 *g_gc = GameConfig2::getInstance();
    GameConfig &g_gc2 = GameConfig::getInstance();
    myfunc();
#endif

#if 0
    using namespace ns2_1;
    SingleInstance *s = SingleInstance::GetInstance();
    s->Print();
    SingleInstance::GetInstance()->Print();
    SingleInstance::deleteInstance();
#endif

#if 1
    using namespace ns2_4;
    getInstance<TestClass>()->print();
    getInstance<TestClass>()->print();

    auto instance1 = getInstance<vector<int>>();
    auto instance2 = getInstance<vector<int>>();
    instance1->push_back(1);
    instance2->push_back(2);
    cout << "instance1->size(): " << instance1->size() << endl;
    cout << "instance2->size(): " << instance2->size() << endl;
    cout << "instance1 address: " << instance1.get() << endl;
    cout << "instance2 address: " << instance2.get() << endl;
#endif

    cout << "Over!\n";
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/240823.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 常用的操作命令

我们习惯的使用Windows,安装软件进行使用&#xff0c;比如 WPS&#xff0c;浏览器&#xff0c;一些工具&#xff0c;但是在Linux上就需要用命令去操作&#xff0c;也可以使用像Ubuntu 和 CentOS这类的可视化面板 Linux系统是开源的&#xff0c;所以开发人员可以反复的发现Bug以…

高项备考葵花宝典-项目进度管理核心方法加强理解-关键路径法

关键路径法&#xff08;Critical Path Method&#xff0c;CPM&#xff09;是一种基于数学计算的项目计划管理方法&#xff0c;是网络图计划方法的一种&#xff0c;属于肯定型的网络图。关键路径法将项目分解成为多个独立的活动并确定每个活动的工期&#xff0c;然后用逻辑关系&…

​hashlib --- 安全哈希与消息摘要​

源码&#xff1a; Lib/hashlib.py 本模块针对许多不同的安全哈希和消息摘要算法实现了一个通用接口。 包括了 FIPS 安全哈希算法 SHA1, SHA224, SHA256, SHA384, SHA512, (定义见 the FIPS 180-4 standard), SHA-3 系列 (定义见 the FIPS 202 standard) 以及 RSA 的 MD5 算法 (…

首场“解数Talk” 直播来了——大模型语料数据联盟开源数据集解读

一、解数 Talk 介绍 为帮助广大开发者更好地了解大模型语料数据联盟发布的AI大模型语料数据&#xff0c;沟通大模型企业在AI视角下的数据需求&#xff0c;不断服务大模型产业生态和落地应用&#xff0c;联盟发起单位上海人工智能实验室联合成员单位共同打造“解数 Talk”系列直…

智能优化算法应用:基于引力搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于引力搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于引力搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.引力搜索算法4.实验参数设定5.算法结果6.…

Vue中发送Ajax请求的方式axios及其跨域问题的解决方案代理机制的配置和原理

Vue中的Ajax请求 现在比较流行的开发方式为异步调用,前后台以异步Ajax请求的方式进行交换数据,传输的数据使用的是JSON Ajax请求发送后,当浏览器接收到服务器的响应内容后不会重新加载整个页面,只会更新网页的部分实现局部刷新的效果 发送AJAX异步请求的常见方式包括 使用浏…

Java 对接企业微信(文本消息推送)

Java 对接企业微信&#xff08;文本消息推送&#xff09; 背景版本代码POM配置实体工具类发送消息测试配置文件配置文件中的参数来源secretcorpidagentid 执行异常原因 文档 背景 公司的项目&#xff0c;通知信息打算接入企业微信通知。提前做下实验。 版本 JDK 21 SpringBoo…

故障排查方法与技巧

判断网络是否稳定&#xff0c;最重要的两个命令 ping 10.28.0.23 -t -l 1000 -t &#xff1a;无限循环ping -l&#xff1a;指定数据包大小 内网环境< 1ms,是较好的网络&#xff0c;如果跳到100多&#xff0c;说明网络不稳定 telnet ip地址空格端口号 表示不通 数据库…

老师发成绩单攻略:5种方法让群发成绩变得更高效

作为老师&#xff0c;发布成绩单是一项重要的任务。为了更高效地完成这项任务&#xff0c;本文将介绍5种方法&#xff0c;帮助老师群发成绩单更加高效。 一、提前规划&#xff0c;做好准备 在发布成绩单之前&#xff0c;老师需要提前规划好发布的时间、方式、接收对象等&#…

路径总和(递归)

112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &a…

34、卷积实战 - 手写一个基础卷积算法

前面基本上把卷积这一算法的原理和公式介绍完了,如果还有不懂的,可以多翻几遍前面的章节内容,深入理解一下。 本节加一个实战,大家可以手动来实现一个卷积算法,本文中以 python 代码为例,C++ 的代码可以查看本节后面的链接。 说到卷积实现,其实就是自己手写一个卷积算…

js基础:简介、变量与数据类型、流程循环控制语句、数组及其api

JS基础&#xff1a;简介、变量与数据类型、流程循环控制语句、数组及其api 一、简介 1、js概述 tip&#xff1a;JavaScript是什么&#xff1f; 有什么作用&#xff1f; JavaScript&#xff08;简称JS&#xff09;是一种轻量级的、解释性的编程语言&#xff0c;主要用于在网页…

SpringCloud微服务(简略笔记二)

Docker 概念 docker和虚拟机的差异 * docker是一个系统进程&#xff1b;虚拟机是在操作系统中的操作系统 * docker体积小&#xff0c;启动速度&#xff0c;性能好&#xff0c;虚拟机体积大&#xff0c;启动速度慢&#xff0c;性能一般 镜像和容器 镜像&#xff08;image&…

多模态统计图表综述:图表分类,图表理解,图表生成,图表大一统模型

Overview 多模态统计图表综述一、图表分类1.1 Survey1.2 常见分类数据集&#xff1a;1.3 常见图表类型 二、图表理解2.1 VQA2..1.1 DVQA CVPR20182.1.2 PlotQA 20192.1.3 ChartQA 2022 2.2 Summary2.2.1 Chart-to-text ACL 2022 三、图表生成四、图表大一统模型4.1 UniChart 20…

stm32 使用18B20 测试温度

用18b20 测试温度是非常常用的&#xff0c;不过18B20的调试不是这么容易的&#xff0c;有些内容网上很多的&#xff0c;不再重复说了&#xff0c;我先把波形说一下&#xff0c;再说程序部分&#xff1a; 整个都温度数据的顺序是&#xff1a; 1.700uS的低电平复位并测试18B20的…

【matlab进阶学习-6】 读取log数据data.txt文件,并做处理,导出报告/表格/图表

原始文件 原始文件格式txt&#xff0c;每一行对应一个数据&#xff0c;数据之间由逗号分割开 对应意思 时刻&#xff0c;电压&#xff0c;电流&#xff0c;功率&#xff0c;容量&#xff0c;&#xff0c;电流&#xff0c;功率&#xff0c;&#xff0c;RTC时间&#xff0c;状态…

什么是电商价格监控

电商价格监控是一种系统爬取数据后的实现动作&#xff0c;比起含义&#xff0c;其实更应该关注为什么要做电商价格监控&#xff0c;电商价格监控的执行前提是品牌要治理渠道&#xff0c;需要将电商平台的低价链接打击干净&#xff0c;那就需要先对低价链接进行确认、筛选&#…

YOLOv8改进 | 2023主干篇 | 利用轻量化卷积优化PP-HGNetV2改进主干(全网独家创新)

一、本文介绍 Hello&#xff0c;大家好&#xff0c;上一篇博客我们讲了利用HGNetV2去替换YOLOv8的主干&#xff0c;经过结构的研究我们可以发现在HGNetV2的网络中有大量的卷积存在&#xff0c;所以我们可以用一种更加轻量化的卷积去优化HGNetV2从而达到更加轻量化的效果&#…

AspNetCore 中使用 Knife4jUI 更加友好的Swagger界面

&#x1f680;介绍 aspnetcore.knife4j是一个基于.NET Core平台的Swagger UI库&#xff0c;它提供了API文档的生成和管理功能。这个库的前身是swagger-bootstrap-ui&#xff0c;在Java项目中广泛使用&#xff0c;由于其优秀的界面和易用性被许多开发者所推崇。现在&#xff0c…

探索Nginx的奥秘--从代理到负载均衡的艺术实践

文章目录 &#x1f33a;Nginx的引入&#x1f33a;&#x1f33a;深刻理解正向代理与反向代理&#x1f33a;&#x1f339;Reverse proxy&#x1f339;&#x1f339;正向代理与反向代理的区别&#x1f339;&#x1f339;反向代理为什么叫反向代理&#x1f339;&#x1f339;负载均…
最新文章