C++ 设计模式之单例模式

#include <QCoreApplication>
#include <iostream>
#include <mutex>
#include <atomic>
#include <queue>
#include <thread>

using namespace std;
#if 0
// 饿汉模式->定义类的时候创建单例对象
// 定义一个单例模式的任务队列
// 多线程场景下,饿汉模式没有线程安全问题
// 线程安全:多线程可以同时访问这个单例对象
class TaskQueue
{
public:
    //    = delete 代表函数的禁用,也可以将其访问权限设置为私有
    //    TaskQueue() = delete;
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator =(const TaskQueue& t) = delete;

    //
    static TaskQueue* getInstance()
    {
        return m_taskQ;
    }

    void printf()
    {
        cout << "112233" << endl;
    }
private:
    //    将构造函数的构造函数设为私有的1
    TaskQueue() = default;
    //    TaskQueue(const TaskQueue& t) = default;
    //    TaskQueue& operator =(const TaskQueue& t) = default;

    // 只能通过类名访问静态属性或方法
    // 静态变量不可以在类的内部进行初始化
    static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

#endif

#if 0
// 懒汉模式->什么时候需要使用这个单例对象,在使用的时候再去创建对应的实例
// 比较节省内存空间
// 需要考虑线程安全 需要加互斥锁
// 原子变量 atomic 通过原子变量可以操作机器指令执行顺序
class TaskQueue
{
    //     = delete 代表函数的禁用,也可以将其访问权限设置为私有
public:
    //    TaskQueue() = delete;
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator =(const TaskQueue& t) = delete;

    //
    static TaskQueue* getInstance()
    {
        TaskQueue* task = m_taskQ.load();
        // 区别 双重检查锁定
        if(task == nullptr) // 1
        {
            m_mutex.lock(); // 锁定
            task = m_taskQ.load(); // 再次读取
            if(task == nullptr) // 2
            {
                // 对应的机器指令可能会被重新排序
                task = new TaskQueue;
                m_taskQ.store(task);
            }
            m_mutex.unlock();
        }

        return task;
    }

    void printf()
    {
        cout << "112233" << endl;
    }
private:
    //    将构造函数的构造函数设为私有的1
    TaskQueue() = default;
    //    TaskQueue(const TaskQueue& t) = default;
    //    TaskQueue& operator =(const TaskQueue& t) = default;

    // 只能通过类名访问静态属性或方法
    // 静态变量不可以在类的内部进行初始化
    //    static TaskQueue* m_taskQ;
    static mutex      m_mutex;
    static atomic<TaskQueue *> m_taskQ;
};
// 区别
atomic<TaskQueue *> TaskQueue::m_taskQ;
//TaskQueue* TaskQueue::m_taskQ = nullptr;
mutex      TaskQueue::m_mutex; // 静态变量在外部需声明

#endif

#if 0
// 懒汉模式->什么时候需要使用这个单例对象,在使用的时候再去创建对应的实例
// 比较节省内存空间
// 需要考虑线程安全 使用静态局部变量解决线程安全问题
// 要求编译器支持c++ 11

class TaskQueue
{
    //     = delete 代表函数的禁用,也可以将其访问权限设置为私有
public:
    //    TaskQueue() = delete;
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator =(const TaskQueue& t) = delete;

    //
    static TaskQueue* getInstance()
    {
        static TaskQueue task;

        return &task;
    }

    void printf()
    {
        cout << "112233" << endl;
    }
private:
    //    将构造函数的构造函数设为私有的1
    TaskQueue() = default;
    //    TaskQueue(const TaskQueue& t) = default;
    //    TaskQueue& operator =(const TaskQueue& t) = default;
};
#endif

#if 1
// 饿汉模式
// 多线程 任务队列
class TaskQueue
{
public:
    //    = delete 代表函数的禁用,也可以将其访问权限设置为私有
    //    TaskQueue() = delete;
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator =(const TaskQueue& t) = delete;

    //
    static TaskQueue* getInstance()
    {
        return m_taskQ;
    }

    void printf()
    {
        cout << "112233" << endl;
    }

    // 判断任务队列是否为空
    bool isEmpty()
    {
        lock_guard<mutex> locker(m_mutex);
        bool flag = m_data.empty();
        return flag;
    }

    // 添加任务
    void addTask(int node)
    {
        lock_guard<mutex> locker(m_mutex);
        m_data.push(node);
    }

    // 删除任务
    bool popTask()
    {
        lock_guard<mutex> locker(m_mutex);
        if(m_data.empty())
        {
            return false;
        }
        m_data.pop();
        return true;
    }

    // 取任务(不删除任务)
    int taskTask()
    {
        lock_guard<mutex> locker(m_mutex);
        if(m_data.empty())
        {
            return -1;
        }
        int data = m_data.front();
        return data;
    }

private:
    //    将构造函数的构造函数设为私有的1
    TaskQueue() = default;
    //    TaskQueue(const TaskQueue& t) = default;
    //    TaskQueue& operator =(const TaskQueue& t) = default;

    // 只能通过类名访问静态属性或方法
    // 静态变量不可以在类的内部进行初始化
    static TaskQueue* m_taskQ;
    // 定义任务队列
    queue<int> m_data;
    // 使用互斥锁保护队列数据
    mutex      m_mutex;
};
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

#endif
int main(int argc, char *argv[])
{
    //    TaskQueue::getInstance()->printf();

    TaskQueue* taskQ = TaskQueue::getInstance();
//    taskQ->printf();
    // 生产者
    thread t1([=]{

              for(int i = 0; i < 5; ++i)
              {
                  taskQ->addTask(i + 100);
                  cout << "push data" << i + 100 << ", thread ID"<<
                       this_thread::get_id()<< endl;
                  this_thread::sleep_for(chrono::milliseconds(500));
              }
             });

    // 消费者
    thread t2([=]{
              this_thread::sleep_for(chrono::milliseconds(100));
              while(!taskQ->isEmpty())
              {
                  int num = taskQ->taskTask();
                  cout << "take data" << num << ", thread ID"<<
                       this_thread::get_id()<< endl;

                  taskQ->popTask();
                  this_thread::sleep_for(chrono::milliseconds(1000));
              }

             });
// 阻塞调用函数的线程
    t1.join();
    t2.join();
    QCoreApplication a(argc, argv);
    return a.exec();


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值