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的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...
随机推荐
- DHTML【10】--Javascript
大家好,这一节主要介绍Javascript的函数.函数是Javascript的核心中的核心,这么强调一点都不过分,相信没有人反对,如果有人反对,你以后可以不用函数,呵呵,说的有点绝了啊. 下面看一下J ...
- 【Unity 3D】学习笔记三十七:物理引擎——碰撞与休眠
碰撞与休眠 上一篇笔记说过,当给予游戏对象刚体这个组件以后,那么这个组件将存在碰撞的可能性.一旦刚体開始运动,那么系统方法便会监视刚体的碰撞状态.一般刚体的碰撞分为三种:进入碰撞,碰撞中,和碰撞结束. ...
- Android_app项目开发步骤总结
做了几个android企业应用项目后,总结了项目的基本开发步骤.希望可以交流. 一 应用规划: ※确定功能. ※必须的界面及界面跳转的流程. ※须要的数据及数据的来源及格 ...
- 祖国版SoloWheel:Airwheel爱尔威火星车 拆箱&上手经验_运动户外_晒物广场_什么值得买
http://m.baidu.com/from=844b/bd_page_type=1/ssid=0/uid=3151E6C0905477A13653132D762BB6FB/pu=sz%401320 ...
- H3C TE BGP拓扑排错报告
BGP排错报告 故障一:PPP链路 ...
- SE 2014年5月5日
如图配置 某企业网络规划图(三台交换设备/三台路由设备) 接入层 SW1 连接终端用户 汇聚层 SW2 SW3 核心层 R1 R2 R5 1. 如图 SW1 SW2 SW3 物理链路两两相连接,网络中 ...
- CSS selectors for Selenium with example,selenium IDE
CSS selectors for Selenium with example http://seleniumeasy.com/selenium-tutorials/css-selectors-tut ...
- 开放源代码的微微信.NET 0.8 版公布了
微微信.NET 0.8 版公布了 A.源代码应用范围: 未认证的和经过认证的微信订阅号.微信服务号均可使用,本源代码的每个模块都提供全然的 ASP.NET C#源代码,绝对不含 ...
- 正确AJAX了解该技术的,创建,应用
ajax认识: 1. ajax这是间client与server机制.但这一机制是在前台的,利用前台的闲置功能,来进行前台与后台的数据交流,以达到增强用户体检.降低server压力,更有效的利用带宽的效 ...
- HDU - 2825 Wireless Password(AC自己主动机+DP)
Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...