Singleton模式线程相关的(C\C++)
这种需求的最新发展。
我需要一个静态类,无论地方,我可以在线程中调用它public功能对应的功能已经完成。
这个静态类会调用我初始化给它的一个指针,这个指针是与线程一一相应的;
准确来说这样的模式应该叫多例模式,它是单例模式和工厂模式的一个变式。
以下说一下,我的实现思路。
(一)实例指针
假设是单例模式,会有一个指针或者静态变量来存储这个静态变量。而这里多例。则须要使用一个Map来存储,Map的key是当前线程的句柄,Map定义例如以下:
typedef map<DWORD, CRelatedThreadMultiton*> ThreadMap;
(二)获取指针
与单例模式同样,构造是私有的,通过静态的接口来获得实例。而与其有所差异的地方在于,假设已经存在于map。我须要从map中拿到相应的instance,而假设不存在。则须要在new之后,将其存放于map中。
因为是线程相关的,也就是说一个线程中仅仅会有一个instance,所以它本质上与单线程的单例模式是类似的,不会存在多线程的危急。
以下是获得单例指针的代码:
// 获得指定的单例
CRelatedThreadMultiton *pInstance = NULL;
if (InstanceExisted(dwThreadId))
{
pInstance = m_ThreadIdMap[dwThreadId];
}
else
{
pInstance = new CRelatedThreadMultiton;
m_ThreadIdMap[dwThreadId] = pInstance;
}
这里推断是否存在。须要通过遍历map表来实现,实现例如以下:
BOOL CRelatedThreadMultiton::InstanceExisted( DWORD _dwThreadId )
{
ThreadMap::iterator itor = m_ThreadIdMap.begin();
while (itor!=m_ThreadIdMap.end())
{
if (itor->first == _dwThreadId)
{
return TRUE;
}
itor++;
} return FALSE;
}
(三)instance的释放
我觉得instance有两个释放时机,一个是我在获得一个新的之前,我能够检查map表中是否有无效的项。假设有。则擦除之。还有一个是在析构的时候须要清空map表,删除指针。
删除无效指针的实现例如以下:
// 删除map中已经失效的指针
BOOL CRelatedThreadMultiton::RemoveInvalidInstance()
{
ThreadMap::iterator itor = m_ThreadIdMap.begin();
while (itor!=m_ThreadIdMap.end())
{
if (!ThreadExisted(itor->first))
{
//delete itor->second;
itor = m_ThreadIdMap.erase(itor);
}
else
itor++;
} return TRUE;
}
这里须要用到推断一个遍历当前进程的线程的方法,能够通过快照的方式遍历。代码不难,仅仅是须要熟悉几个经常使用的API,能够例如以下实现:
// 遍历当前进程的全部线程。推断当前进程是否存在
BOOL CRelatedThreadMultiton::ThreadExisted(DWORD _dwThreadId)
{
BOOL bRet = FALSE;
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 threadEntry32; // 创建当前进程的快照
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return FALSE; threadEntry32.dwSize = sizeof(THREADENTRY32 ); // 获得快照的第一个线程
if( !Thread32First( hThreadSnap, &threadEntry32 ) )
{
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return FALSE;
} // 依次遍历全部线程。检查是否存在该线程
do
{
if (threadEntry32.th32ThreadID == _dwThreadId)
{
bRet = TRUE;
break;
}
} while( Thread32Next(hThreadSnap, &threadEntry32 ) ); CloseHandle( hThreadSnap ); // 关闭快照 return bRet;
}
</pre><span style="white-space:pre"> </span>(四)析构</p><p><span style="white-space:pre"> </span>事实上,本质上来说,这个线程相关的多例模式就是一个单例模式。能够全然依照单例模式自己主动析构的方法进行析构。</p><p><span style="white-space:pre"> </span>定义一个内部类。声明其相应的静态成员变量。 </p><p><pre name="code" class="cpp"> class CGarbo // 用于在析构函数中释放各个Instance句柄
{
public:
~CGarbo()
{
RemoveInvalidInstance();
}
};
static CGarbo garbo;
须要注意的是,静态的类成员变量,定义和声明是须要分开的,类内声明,类外定义,不多说,以下是map和garbo成员的定义与初始化:
// 为静态成员变量定义
ThreadMap CRelatedThreadMultiton::m_ThreadIdMap;
CRelatedThreadMultiton::CGarbo CRelatedThreadMultiton::garbo;
(五)初始化线程数据与使用线程数据
为了更方便的測试,我们定义一个类,用于模拟线程相应的数据结构,
该測试类例如以下:
typedef struct _testStruct
{
int a;
int b;
int c;
}testStruct;
然后提供一个PrintC接口用于对外输出
public:
BOOL PrintC();
BOOL CRelatedThreadMultiton::PrintC()
{
printf("c:%d\n", m_pTest->c); return TRUE;
}
最后写两个线程。用于測试。我们的结果怎样:
// test.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include "Multiton.h" #include<iostream>
#include <process.h> using namespace std; //DWORD WINAPI SubThread1(LPVOID lpParam)
unsigned _stdcall SubThread1(void* param)
{
testStruct test;
test.c = 1; CRelatedThreadMultiton *pInstance = NULL;
pInstance = CRelatedThreadMultiton::GetRTMultiton();
pInstance->Init((PVOID *)&test); while(TRUE)
{
pInstance->PrintC(); static int j =0;
j++;
if (j>10)
{
break;
}
Sleep(500);
} return 0;
} unsigned _stdcall SubThread2(void* param)
{
testStruct test;
test.c = 2; CRelatedThreadMultiton *pInstance = NULL;
pInstance = CRelatedThreadMultiton::GetRTMultiton();
pInstance->Init((PVOID *)&test); while(TRUE)
{
pInstance->PrintC(); static int i =0;
i++;
if (i>10)
{
break;
}
Sleep(1000);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD hProcess = GetCurrentProcessId(); HANDLE hThread1;
HANDLE hThread2; unsigned int uThreadID1;
unsigned int uThreadID2; hThread1 = (HANDLE)_beginthreadex(NULL, 0, SubThread1, NULL, NULL, &uThreadID1);
hThread2 = (HANDLE)_beginthreadex(NULL, 0, SubThread2, NULL, NULL, &uThreadID2); ::WaitForSingleObject(hThread1, INFINITE);
::WaitForSingleObject(hThread2, INFINITE); _endthreadex(uThreadID1);
_endthreadex(uThreadID2); return 0;
}
最后,放一下打印的结果:
ok,如今已经实现了最初希望的目标,假设有不论什么建议和问题,欢迎大家斧正,谢谢!~
近期发现自己的博客居然和自己做事一般麻乱。甚是烦躁,趁着端午节假期期间,准备做个小的调整。另,须要学的东西真的好多。就拿设计模式来说,略微有些编程经验的,一两个小时也能看懂其目的和实现技术。更专家一些。甚至能够自己再独立实现。可是。工作中慢慢用来,才应了陆游的一句诗词“纸上得来终觉浅,须知此事要躬行。”
被觉得是最简单的一个单例模式,在面对多线程的时候,都须要有番考量才敢用之。
贴上project的0分下载地址:
http://download.csdn.net/detail/fukainankai/7425211
版权声明:本文博客原创文章,博客,未经同意,不得转载。
Singleton模式线程相关的(C\C++)的更多相关文章
- (转)Spring中Singleton模式的线程安全
不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...
- 剑指Offer面试题:1.实现Singleton模式
说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...
- 懒人模式Singleton模式Meyers版本号
直接看代码: /* Singleton模式保证:在一个程序,,一个类有且只有一个实例.并提供一个访问 它的全局访问点 在编程其中.很多情况下,需要确保有一类的一个实例 比如: windopws系统中仅 ...
- C++实现Singleton模式(effective c++ 04)
阅读effective c++ 04 (31页) 提到的singleton设计模式.了解一下. 定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享. 应用场景: 比 ...
- 剑指Offer对答如流系列 - 实现Singleton模式
目录 面试题2:实现Singleton模式 一.懒汉式写法 二.饿汉式写法 三.枚举 面试题2:实现Singleton模式 题目:设计一个类,我们只能生成该类的一个实例. 由于设计模式在面向对象程序设 ...
- 6、单例模式 Singleton模式 只有一个实例 创建型模式
1.了解Singleton模式 程序在运行时,通常都会生成很多实例.例如,表示字符串的java . lang . string类的实例与字符串是- -对- -的关系,所以当有1000个字符串的时候,会 ...
- 《剑指offer》面试题2:实现Singleton 模式
面试题2:实现Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例. 只能生成一个实例的类是实现了Singleton (单例)模式的类型.由于设计模式在面向对象程序设计中起着举足 ...
- C++ Singleton模式
地址:http://www.cppblog.com/dyj057/archive/2005/09/20/346.html Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却 ...
- 进程 & 线程相关知识
不管Java,C++都有进程.线程相关的内容.在这里统一整理吧. Python的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...
随机推荐
- win7下硬盘安装win7+CentOS双系统方法
原文:win7下硬盘安装win7+CentOS双系统方法 LinuxCentOS安装大致介绍: win7下硬盘安装win7+CentOS双系统方法 原则: 所有的看完在装,请仔细看 一 条件: 1. ...
- hdu4521(线段树+dp)
传送门:小明系列问题——小明序列 题意:有n个数,求间距大于d的最长上升序列. 分析:dp[i]表示在i点以a[i]结束距离大于d的最长上升序列,然后每更新到第i点时,取i-d之前小于a[i]的数为结 ...
- 23、Cocos2dx 3.0游戏开发找小三之粒子系统:你那里下雪了吗?
重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/30485919 春雨惊春清谷天,夏满芒夏暑相连, 秋处 ...
- 物联网 开发板 基于ESP8266
The ESP8266 The ESP8266 is a highly integrated chip designed for the needs of an increasingly connec ...
- Kdd Cup 2013 总结2
- OpenStack镜像管理3
第三部分 OpenStack镜像管理 一.简介 很多源都有为OpenStack已经编译好的各种镜像了,您可以直接下载并通过使用这些镜像来熟悉OpenStack. 不过如果是为生产环境进行部署的话,您一 ...
- vi 按了ctrl+s之后
再windows不管是写程序.还是用Word写文件.已经习惯了按ctrl+s 保存代码. 在用vi的时候.常常无意中按了ctrl+s,结果就是如同终端死掉了一样. 这是由于ctrl+s 终止屏幕输出( ...
- cocos2D-x 3.5 引擎解析之--引用计数(Ref),自己主动释放池(PoolManager),自己主动释放池管理器( AutoreleasePool)
#include <CCRef.h> Ref is used for reference count manangement. If a classinherits from Ref. C ...
- 《javascript高级编程》读书笔记(三)变量、范围和内存的问题
第四章:变量.范围和内存的问题 检測类型:typeof是确定一个变量是字符串.数值.布尔值,还是undefined的最佳工具.可是假设变量的值是一个对象或null,typeof仅仅会返回" ...
- zimbra启用SMTP认证并绑定认证登录和发件人
1. smtp认证 1.1 修改mynetworks 登录zimbra后台-->全局配置-->MTA-->信任网络-->127.0.0.0/8 ...