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的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...
随机推荐
- myeclipse 那个版本号好用?
myeclipse 那个版本号好用? 有没有现成的下载地址?
- Ubuntu12.04password正确 入口的桌面(测试的恢复正常)
举行了两次会议ubuntu输入password正确,但高考制度,输入password后,跳转看接口 后来又返回到登录界面,这个周期已经输入password. 解决方案:1.输入tty下 ...
- 浅析ArrayList,LinkedList的执行效率
以前见过很多文章说这两个东西,感觉自己还是没有深入理解,今天看了书明白一些,在此提出来和大家共同探讨: 面试的时候(基础)一般会问你使用过LinkedList或者ArrayList没有,简单的回答有或 ...
- RabbitMq消息序列化简述
涉及网络传输的应用.序列化不可避免. 发送端以某种规则将消息转成byte数组进行发送. 接收端则以约定的规则进行byte[]数组的解析. 序列化的选择能够是jdk序列化,hessian,jackson ...
- libgdx如何调用android平台内容
使用libgdx已经有一段时间了.最近经常有朋友问我如何在libgdx中调用android的内容. 正常来说libgdx是跨平台的,gdx中的代码是不允许有任何其他平台的相关代码,但实际使用时经常会有 ...
- 不用Root权限获取已经安装的Apk安装包
在安卓设备上安装的apk都会被保留一份在/data/app目录下,但是该目录对于普通用户来说只有可执行权限,是无法访问的. 但是其子文件具有可读权限. 意思也就说我们直接去查看/data/app这个目 ...
- 快捷找jar包方式
通过例如以下站点查找jar包: 1.http://www.java2s.com/Code/Jar/o/Downloadorgapacheservicemixbundlescommonslang246j ...
- hdu 4472 Count (递推)
Count Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- CSS3影子 box-shadow使用和技巧总结
text-shadow阴影效果添加到文本,box-shadow块元素被添加到周围的阴影. 随着html5和CSS3声望.越来越普遍的使用特效. 基本语法这是{box-shadow:[inset] x- ...
- windows phone 获取手机图片库中图片(4)
原文:windows phone 获取手机图片库中图片(4) 前置条件:手机和电脑未连接或连接电脑Zune软件关闭(与Zune软件连接时不允许访问图片库): 版本7.1 获取手机图片库图片的两种方式: ...