请问做ppt换模板在哪里/(ppt做好了如何换模板)
614
2022-05-30
文章目录
前言
享元模式与池技术
享元模式定义与结构
线程池
对象池类图
对象池代码实现
前言
之前写“桥接模式”的时候,说“桥接模式”是最抽象的设计模式,那是因为我没接触到“享元模式”。
可能桥接模式是最抽象的设计模式,但是享元模式我觉得是最烦的设计模式了。
因为这个模式和“
池技术
”有着
密不可分
的联系。
享元模式与池技术
说到享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池、线程池等等都是享元模式的应用,所以说享元模式是池技术和池技术密不可分。
面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。享元模式正是为解决这一类问题而诞生的。享元模式通过共享技术实现相同或相似对象的重用。
享元模式定义与结构
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于 享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种 对象结构型模式。
线程池
心里没底,还是先来个线程池压压惊吧。
//pthreadpool.h #pragma once #include //据说list不安全,不安全就不安全吧,更不安全的都忍了 #include "Cond.h" //封装过的条件变量类,继承自封装的mutex锁类,所以具有锁和条件变量的双重属性 using namespace std; class Task //任务接口,每个任务必须实现的接口,以供工作线程调度任务的执行 { public: Task() {} virtual ~Task() {} virtual int run() = 0; //留给子类实现 }; typedef list
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
//pthreadpool.cpp #include "Pthread_Pool.h" //开放接口1 Pthread_Pool::Pthread_Pool(unsigned int max, unsigned int min, unsigned int wait) { //配置基本参数 count = 0; //当前线程池为空 waitcount = 0; //没有等待线程 mincount = min; //核心线程数(出厂配置) maxcount = max; //最大线程数(能承受的最高配置) waitsec = wait; //线程保活时长(过了时长还没接到任务,那就裁掉) Stop = false; //允许运作 //上锁,创建一定数量的线程作为初始线程池 cond.lock(); for (unsigned i = 0; i < mincount; i++) { createThread(); //跳转到这个函数的实现->->->->-> } cond.unlock(); } Pthread_Pool::~Pthread_Pool() { destroyThread(); //销毁线程池 } void Pthread_Pool::createThread() { pthread_t tid; int ret = pthread_create(&tid, NULL, taskThread, (void*)this); //以执行taskThread()为目的创建线程,跳转到taskThread()函数的实现 ->->->->-> if (ret < 0) perror("pthread create error"); else count++; } // 工作线程 void* Pthread_Pool::taskThread(void* arg) { pthread_detach(pthread_self()); //设置线程自分离属性 Pthread_Pool* pool = (Pthread_Pool*)arg; while (1) { pool->cond.lock(); //如果没有工作线程在等待 if (pool->taskList.empty()) { if (pool->Stop) //当收到线程池停止运行的消息时 { pool->count--; //线程数减一 pool->cond.unlock(); pthread_exit(NULL); //本线程强制退出 } pool->waitcount++; //等待任务的线程数加一 bool bSignal = pool->cond.timewait(pool->waitsec); //新任务等待被唤醒 pool->waitcount--; //没等到,没事干,喝西北风了 // 删除无用线程 if (!bSignal && pool->count > pool->mincount) //如果没事干 && 有多余线程 { pool->count--; //先裁员一个,不要一次做绝了,反正是在while循环里面,没事干裁员机会多得是 pool->cond.unlock(); pthread_exit(NULL); } } pool->cond.unlock(); //记得要释放锁 //如果有工作线程在等待 if (!pool->taskList.empty()) { pool->taskCond.lock(); //上任务锁 Task* t = pool->taskList.front(); //获取任务队列中最前端的任务并执行 pool->taskList.pop_front(); //移除被领取的任务 pool->taskCond.unlock();//记得解锁 t->run(); //任务开始 delete t; //弄完就删了 } } pthread_exit(NULL); } //开放接口2,向任务队列中添加任务 void Pthread_Pool::addTask(Task* task) { if (Stop) //线程池是否停止工作 return; //向任务队列中添加新任务 taskCond.lock(); //上任务锁 taskList.push_back(task); //添加任务 taskCond.unlock(); //记得解锁 cond.lock(); //上线程锁 if (waitcount) //如果有空闲线程 { cond.signal(); //唤醒一个线程 } else if (count < maxcount) //如果没有空闲线程,一般来说,走到这里面来,那这个线程池的设计是有点失败了 { createThread(); //那就创建一个 cond.signal(); //然后唤醒 } cond.unlock(); } void Pthread_Pool::destroyThread() { printf("destroy?\n"); #if 0 //强行清理 list_task::iterator it = taskList.begin(); for (; it!= taskList.end(); it++) { Task* t = *it; delete t; t = NULL; } taskList.clear(); #endif // 等待所有线程执行完毕 Stop = true; while (count > 0) { cond.lock(); cond.broadcast(); //广播 cond.unlock(); sleep(1); } }
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
调用的地方是这样的:
class DoTask : public Task { public: DoTask(BtoC& send, PacketCommand1& packet); int run(); private: DB_command* task_db; BtoC* m_send; PacketCommand1 m_packet; PacketCommand3* f_packet; }; class BackServer { public: BackServer(char* IPnum); ~BackServer() {} int run(); private: PacketCommand1 m_packet; BtoC m_send; Pthread_Pool* m_pool; };
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
int BackServer::run() { int n = 0; while (1) { n = m_send.Read_date(m_packet.getData()); m_packet.setSize(n); DoTask* t = new DoTask(m_send, m_packet); m_pool->addTask(t); } return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
在这个线程池中呢,可以看到负责创建线程和管理线程的函数(享元工厂)、每条线程的共用属性(外部属性)、传递给每个线程的不同任务(内部属性),还有负责缓冲的任务队列。
这些部分(享元工厂、元素外部属性、元素内部属性),就是享元模式的主要构成。
不过,在线程池调用的过程中,确是存在了一个问题:
DoTask* t = new DoTask(m_send, m_packet)
;这个可不见得回收了,要是等着系统的垃圾回收机制也是可以的,但是在高并发的情况下,这些尸位素餐的
DoTask* t
无疑成为了等待资源的任务们的“公敌”。
那么,今天我就来弄一个对象池,解决这个问题。
对象池类图
对象公有属性: (SignInfo)
DB_command* task_db; PacketCommand3* f_packet;
1
2
对象公有方法:
virtual int run(); virtual void setidentify(string identify); virtual string getidentify();
1
2
3
对象私有属性:(SignInfoPool)
BtoC* m_send; PacketCommand1 m_packet; string identify; //身份标识 int state; //是否处于空闲态
1
2
3
4
对象私有方法:
int run(); void setidentify(string identify); string getidentify();
1
2
3
享元工厂属性:
map
1
享元工厂方法:
SignInfo* getSignInfo(string identify);
1
这样可好?
画个图看看:
接下来代码实现看看。
对象池代码实现
#include
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
初次上手“享元模式”,多有纰漏,再写之时会整合成一个类,像线程池那样。
任务调度
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。