单例模式
单例模式就是一种“经典的,常用的,常考的” 设计模式
什么是设计模式
大佬对于一些常见的场景,给定了一个特定对应的解决方案,这个就是设计模式,这个是可以被推广使用的
单例模式的特定
某些类,只应该需要又一个对象(实例),就称为单例
例如:一个男人只能取一个老婆
类 对象
threadpool tp
定义一个对象:开辟空间+给空间写入初始值(本质上就是将对象加载到内存里面)
只让该对象在内存中存在一份,加载一次
一般而言,我们的对象被设计称单例模式
- 语意上,我们只需要一个
- 该对象内部存在有大量的空间,保存了大量的数据,如果允许该对象存在多份的话,或者允许发生各自拷贝,内存中存在冗余数据
这一般情况下,我们都可以设计成为单例模式
那么什么时候创建呢?
1. 饿汉模式
吃完饭,立刻洗碗,因为这样,吃下一顿的时候立刻就能把饭拿到手里
饿汉模式实现单例模式
1 2 3 4 5 6 7 8 9 10 11 12
| template<class T> class singleton{ static T data; public: static T* getinstance() { return &data; }
}
|
只通过singleton这个包装类来使用T 对象,则一个进程中只有一个T 对象的实例
像这种静态成员,只要创建了一个对象这个静态成员立刻就开辟了,这就叫做饿汉模式
2. 懒汉模式
吃完饭,先把碗放下来,等到下一次要吃饭的时候再去洗这个碗
(延迟加载),在用的时候再加载,
写时拷贝(在用的时候,再拷贝),申请空间(不需要的时候就不用再做),优化服务器的启动速度
懒汉模式创建单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template<class T>
class singleton { static T* inst; public: static T*getinstance() { if(inst==NULL) { inst=new T(); } return inst; } }
|
智能指针是线程安全的
单例模式实现线程池
task
task.hpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #pragma once #include <iostream> #include <pthread.h>
namespace ns_task { class Task { private: int _x; int _y; char _op; public: Task() { } Task(int x, int y, char op) : _x(x), _y(y), _op(op) { } ~Task() { } int Run() { int res = 0; switch (_op) { case '+': res = _x + _y; break; case '-': res = _x - _y; break; case '*': res = _x * _y; break; case '/': res = _x / _y; break; case '%': res = _x % _y; break; default: std::cout << "bug?" << std::endl; break; } std::cout << "当前任务正在被:" << pthread_self() << "处理:" << _x << _op << _y << "=" << res << std::endl; return res; } Task operator=(Task &s) { if (this != &s) { _x = s._x; _y = s._y; _op = s._op; } return *this; } int operator()() { return Run(); } }; }
|
threadpool
threadpool.hpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| #pragma once #include <iostream> #include <string> #include <queue> #include <unistd.h> #include <pthread.h>
namespace ns_threadpool { const int g_num = 5; template <class T> class ThreadPool {
private: int num_; std::queue<T> task_queue_; pthread_mutex_t mtx_; pthread_cond_t cond_; static ThreadPool<T> *ins; private: ThreadPool(int num = g_num) : num_(num) { pthread_mutex_init(&mtx_, nullptr); pthread_cond_init(&cond_, nullptr); }
ThreadPool(const ThreadPool &tp) = delete;
ThreadPool operator=(const ThreadPool &tp) = delete;
public: static ThreadPool<T> *GetInstance() {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
if (ins == nullptr)
{
pthread_mutex_lock(&lock);
if (ins == nullptr) { ins = new ThreadPool<T>(); ins->InitThreadPool(); std::cout << "首次加载对象" << std::endl; } pthread_mutex_unlock(&lock); } return ins; }
~ThreadPool() { pthread_mutex_destroy(&mtx_); pthread_cond_destroy(&cond_); }
static void *Rountine(void *args) {
pthread_detach(pthread_self()); ThreadPool<T> *tp = (ThreadPool<T> *)args; while (true) {
tp->Lock(); while (tp->IsEmpty()) { tp->Wait(); } T t; tp->PopTask(&t); tp->UnLock(); t.Run();
sleep(1); } } void InitThreadPool() { pthread_t tid; for (int i = 0; i < num_; i++) { pthread_create(&tid, nullptr, Rountine, (void *)this); } } void PopTask(T *out) { *out = task_queue_.front(); task_queue_.pop(); } void Wait() { pthread_cond_wait(&cond_, &mtx_); } bool IsEmpty() { return task_queue_.empty(); } void Lock() { pthread_mutex_lock(&mtx_); } void UnLock() { pthread_mutex_unlock(&mtx_); } void Wakeup() { pthread_cond_signal(&cond_); } void PushTask(const T &in) { Lock(); task_queue_.push(in); UnLock(); Wakeup(); }
}; template <class T> ThreadPool<T> *ThreadPool<T>::ins = nullptr;
}
|
main
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include "threadpool.hpp" #include "Task.hpp" #include <unistd.h> #include <cstdlib> #include <ctime> using namespace ns_task; using namespace ns_threadpool;
int main() { std::cout << "当前正在执行我的进程其他代码......" << std::endl; std::cout << "当前正在执行我的进程其他代码......" << std::endl; std::cout << "当前正在执行我的进程其他代码......" << std::endl; std::cout << "当前正在执行我的进程其他代码......" << std::endl; std::cout << "当前正在执行我的进程其他代码......" << std::endl; sleep(5); srand((long long)time(nullptr)); while (true) {
sleep(1); Task t(rand() % 20 + 1, rand() % 10 + 1, "+-*/%"[rand() % 5]); ThreadPool<Task>::GetInstance()->PushTask(t); } return 0; }
|