我用過的設(shè)計模式(7)--享元模式

      網(wǎng)友投稿 752 2025-04-03

      文章目錄

      前言

      享元模式與池技術(shù)

      享元模式定義與結(jié)構(gòu)

      線程池

      對象池類圖

      對象池代碼實現(xiàn)

      前言

      之前寫“橋接模式”的時候,說“橋接模式”是最抽象的設(shè)計模式,那是因為我沒接觸到“享元模式”。

      可能橋接模式是最抽象的設(shè)計模式,但是享元模式我覺得是最煩的設(shè)計模式了。

      因為這個模式和“

      池技術(shù)

      ”有著

      密不可分

      的聯(lián)系。

      享元模式與池技術(shù)

      說到享元模式,第一個想到的應(yīng)該就是池技術(shù)了,String常量池、數(shù)據(jù)庫連接池、緩沖池、線程池等等都是享元模式的應(yīng)用,所以說享元模式是池技術(shù)和池技術(shù)密不可分。

      面向?qū)ο蠹夹g(shù)可以很好地解決一些靈活性或可擴展性問題,但在很多情況下需要在系統(tǒng)中增加類和對象的個數(shù)。當(dāng)對象數(shù)量太多時,將導(dǎo)致運行代價過高,帶來性能下降等問題。享元模式正是為解決這一類問題而誕生的。享元模式通過共享技術(shù)實現(xiàn)相同或相似對象的重用。

      享元模式定義與結(jié)構(gòu)

      享元模式(Flyweight Pattern):運用共享技術(shù)有效地支持大量細粒度對象的復(fù)用。系統(tǒng)只使用少量的對象,而這些對象都很相似,狀態(tài)變化很小,可以實現(xiàn)對象的多次復(fù)用。由于 享元模式要求能夠共享的對象必須是細粒度對象,因此它又稱為輕量級模式,它是一種 對象結(jié)構(gòu)型模式。

      線程池

      心里沒底,還是先來個線程池壓壓驚吧。

      //pthreadpool.h #pragma once #include #include #include //據(jù)說list不安全,不安全就不安全吧,更不安全的都忍了 #include "Cond.h" //封裝過的條件變量類,繼承自封裝的mutex鎖類,所以具有鎖和條件變量的雙重屬性 using namespace std; class Task //任務(wù)接口,每個任務(wù)必須實現(xiàn)的接口,以供工作線程調(diào)度任務(wù)的執(zhí)行 { public: Task() {} virtual ~Task() {} virtual int run() = 0; //留給子類實現(xiàn) }; typedef list list_task; //任務(wù)隊列,用于暫存等待處理的任務(wù),等待線程喚醒時處理,提供一種緩沖機制。 class Pthread_Pool //線程池類 { public: Pthread_Pool(unsigned int max = 100, unsigned int min = 10, unsigned int wait = 60); ~Pthread_Pool(); void addTask(Task* task); // 往任務(wù)隊列中添加新線程 private: static void* taskThread(void* arg);// 工作線程 void createThread(); // 新建一個線程 void destroyThread(); // 銷毀一個線程池 unsigned int maxcount; // 最大線程數(shù) unsigned int mincount; // 最小線程數(shù) unsigned int count; // 當(dāng)前線程池中線程數(shù) unsigned int waitcount; // 等待線程數(shù) unsigned int waitsec; // 等待時間 list_task taskList; //任務(wù)隊列 Cond taskCond; //任務(wù)鎖,線程接任務(wù)時使用 Cond cond; //線程鎖,創(chuàng)建線程時使用 bool Stop; //線程池是否被允許運作,初始化線程池對象時置0,線程池銷毀時置為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

      //pthreadpool.cpp #include "Pthread_Pool.h" //開放接口1 Pthread_Pool::Pthread_Pool(unsigned int max, unsigned int min, unsigned int wait) { //配置基本參數(shù) count = 0; //當(dāng)前線程池為空 waitcount = 0; //沒有等待線程 mincount = min; //核心線程數(shù)(出廠配置) maxcount = max; //最大線程數(shù)(能承受的最高配置) waitsec = wait; //線程保活時長(過了時長還沒接到任務(wù),那就裁掉) Stop = false; //允許運作 //上鎖,創(chuàng)建一定數(shù)量的線程作為初始線程池 cond.lock(); for (unsigned i = 0; i < mincount; i++) { createThread(); //跳轉(zhuǎn)到這個函數(shù)的實現(xiàn)->->->->-> } cond.unlock(); } Pthread_Pool::~Pthread_Pool() { destroyThread(); //銷毀線程池 } void Pthread_Pool::createThread() { pthread_t tid; int ret = pthread_create(&tid, NULL, taskThread, (void*)this); //以執(zhí)行taskThread()為目的創(chuàng)建線程,跳轉(zhuǎn)到taskThread()函數(shù)的實現(xiàn) ->->->->-> if (ret < 0) perror("pthread create error"); else count++; } // 工作線程 void* Pthread_Pool::taskThread(void* arg) { pthread_detach(pthread_self()); //設(shè)置線程自分離屬性 Pthread_Pool* pool = (Pthread_Pool*)arg; while (1) { pool->cond.lock(); //如果沒有工作線程在等待 if (pool->taskList.empty()) { if (pool->Stop) //當(dāng)收到線程池停止運行的消息時 { pool->count--; //線程數(shù)減一 pool->cond.unlock(); pthread_exit(NULL); //本線程強制退出 } pool->waitcount++; //等待任務(wù)的線程數(shù)加一 bool bSignal = pool->cond.timewait(pool->waitsec); //新任務(wù)等待被喚醒 pool->waitcount--; //沒等到,沒事干,喝西北風(fēng)了 // 刪除無用線程 if (!bSignal && pool->count > pool->mincount) //如果沒事干 && 有多余線程 { pool->count--; //先裁員一個,不要一次做絕了,反正是在while循環(huán)里面,沒事干裁員機會多得是 pool->cond.unlock(); pthread_exit(NULL); } } pool->cond.unlock(); //記得要釋放鎖 //如果有工作線程在等待 if (!pool->taskList.empty()) { pool->taskCond.lock(); //上任務(wù)鎖 Task* t = pool->taskList.front(); //獲取任務(wù)隊列中最前端的任務(wù)并執(zhí)行 pool->taskList.pop_front(); //移除被領(lǐng)取的任務(wù) pool->taskCond.unlock();//記得解鎖 t->run(); //任務(wù)開始 delete t; //弄完就刪了 } } pthread_exit(NULL); } //開放接口2,向任務(wù)隊列中添加任務(wù) void Pthread_Pool::addTask(Task* task) { if (Stop) //線程池是否停止工作 return; //向任務(wù)隊列中添加新任務(wù) taskCond.lock(); //上任務(wù)鎖 taskList.push_back(task); //添加任務(wù) taskCond.unlock(); //記得解鎖 cond.lock(); //上線程鎖 if (waitcount) //如果有空閑線程 { cond.signal(); //喚醒一個線程 } else if (count < maxcount) //如果沒有空閑線程,一般來說,走到這里面來,那這個線程池的設(shè)計是有點失敗了 { createThread(); //那就創(chuàng)建一個 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 // 等待所有線程執(zhí)行完畢 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

      我用過的設(shè)計模式(7)--享元模式

      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

      調(diào)用的地方是這樣的:

      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

      在這個線程池中呢,可以看到負責(zé)創(chuàng)建線程和管理線程的函數(shù)(享元工廠)、每條線程的共用屬性(外部屬性)、傳遞給每個線程的不同任務(wù)(內(nèi)部屬性),還有負責(zé)緩沖的任務(wù)隊列。

      這些部分(享元工廠、元素外部屬性、元素內(nèi)部屬性),就是享元模式的主要構(gòu)成。

      不過,在線程池調(diào)用的過程中,確是存在了一個問題:

      DoTask* t = new DoTask(m_send, m_packet)

      ;這個可不見得回收了,要是等著系統(tǒng)的垃圾回收機制也是可以的,但是在高并發(fā)的情況下,這些尸位素餐的

      DoTask* t

      無疑成為了等待資源的任務(wù)們的“公敵”。

      那么,今天我就來弄一個對象池,解決這個問題。

      對象池類圖

      對象公有屬性: (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; //身份標(biāo)識 int state; //是否處于空閑態(tài)

      1

      2

      3

      4

      對象私有方法:

      int run(); void setidentify(string identify); string getidentify();

      1

      2

      3

      享元工廠屬性:

      map> mapSign; //hashmap不會用

      1

      享元工廠方法:

      SignInfo* getSignInfo(string identify);

      1

      這樣可好?

      畫個圖看看:

      接下來代碼實現(xiàn)看看。

      對象池代碼實現(xiàn)

      #include #include #include #include using namespace std; class SignInfo { private: int db_task; //用int替代吧 int f_packet; public: virtual int run() = 0; virtual void setidentify(string identify) = 0; virtual string getidentify() = 0; virtual int isRun() = 0; }; class SignInfoPool : public SignInfo { private: string identify; int m_send; int m_packet; int state; //是否在使用 public: SignInfoPool() { this->state = 0; } //實例化對象時使用 void setInfo(int m_send, int m_packet) { this->m_send = m_send; this->m_packet = m_packet; }; //工廠生產(chǎn)的時候使用 void setidentify(string identify) { this->identify = identify; } string getidentify() { return this->getidentify(); } void setState(int state) { this->state = state; } int getState() { return this->state; } int isRun() { return this->state; } //在運行返回1.沒運行返回0 int run() { cout << identify << " dosomething" << endl; } }; class SignInfoFactory { private: map> mapSignInfo; int maxi; //最大對象數(shù) int mini; //核心對象數(shù) public: SignInfoFactory(int maxi,int mini) { this->maxi = maxi; this->mini = mini; createsigninfo("DBlogin"); //初始化一些用來處理登錄的對象 createsigninfo("DBregist"); //初始化一些用來處理注冊的對象 createsigninfo("DBfpwd"); //初始化一些用來處理密碼的對象 createsigninfo("DBfile"); //初始化一些用來處理文件的對象 } //初始化一些新對象 void createsigninfo(string identify) { vector temp; SignInfo* signinfo; for (int i = 0; i < mini; i++) { signinfo = new SignInfoPool(); signinfo->setidentify(identify); temp.push_back(signinfo); } mapSignInfo[identify] = temp; } SignInfo* getSignInfo(string identify) { int size = (mapSignInfo[identify]).size(); for (int i = 0; i < size; i++) { if (!(mapSignInfo[identify])[i]->isRun()) { return (mapSignInfo[identify])[i]; } } } void DestoryFactory() { //這。。。我也想知道怎么銷毀。。。map沒有迭代器啊。。。 } //結(jié)束時的工廠銷毀 };

      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

      初次上手“享元模式”,多有紕漏,再寫之時會整合成一個類,像線程池那樣。

      任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:excel2007表格數(shù)據(jù)透視如何制作(數(shù)據(jù)透視表怎么做excel2010)
      下一篇:2013excel表格如何去重
      相關(guān)文章
      亚洲国产精品人久久电影| 亚洲美女在线观看播放| 亚洲av永久无码精品漫画| 亚洲精品一卡2卡3卡四卡乱码| 97亚洲熟妇自偷自拍另类图片| 久久久综合亚洲色一区二区三区| 国产亚洲情侣一区二区无| 亚洲欧洲自拍拍偷精品 美利坚| 亚洲AV日韩AV无码污污网站 | 亚洲第一页在线观看| 亚洲av鲁丝一区二区三区| 久久精品亚洲中文字幕无码网站| 亚洲成AV人片在| 亚洲成在人天堂在线| 亚洲视频在线免费观看| 久久亚洲精品无码| 亚洲五月激情综合图片区| 亚洲国产精品久久久久久| 亚洲国产高清人在线| 91精品国产亚洲爽啪在线影院| 久久亚洲精品无码VA大香大香| 亚洲最大在线观看| 亚洲人成人77777在线播放| 亚洲一级毛片视频| 亚洲高清视频在线| 亚洲jizzjizz少妇| 亚洲AV中文无码乱人伦| 亚洲精品国精品久久99热| 亚洲片国产一区一级在线观看| 国产亚洲精品观看91在线| 日韩欧美亚洲中文乱码| 亚洲Av永久无码精品一区二区| 久久久久久亚洲精品无码| 国产亚洲精彩视频| 国产精品亚洲综合专区片高清久久久 | 亚洲国产成a人v在线观看| 亚洲国产精品免费观看| 国产成人精品久久亚洲高清不卡 | 欧洲亚洲综合一区二区三区| 亚洲日韩人妻第一页| 国产亚洲成av片在线观看|