#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();
}
C++ 设计模式之单例模式
最新推荐文章于 2024-10-08 06:04:53 发布