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的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...
随机推荐
- 在RHEL上安装Thrift(支持C++)的若干问题 » 编码无悔 / Intent & Focused
在RHEL上安装Thrift(支持C++)的若干问题 » 编码无悔 / Intent & Focused [原创]在RHEL上安装Thrift(支持C++)的若干问题 2010年12月1 ...
- 自编Ps教程—我的ps图片赞赏
上篇讲述了主要的ps概念和操作,这里不再讲述了,主要的操作学好了,其它的都简单,下面我会把我闲暇时间天马行空的小作品上穿,以供大家闲暇时间或者工作累了的时候赞赏! 以后还会在这里上传哦!喜欢就收藏吧! ...
- Servlet(二)GenericServlet
以GenericServlet创建Servlet 1.在FirstServlet同文件夹下建立GServlet.java package com.hunhun; import javax.servle ...
- three.js是JavaScript编写的WebGL第 三方库
three.js是JavaScript编写的WebGL第 三方库.提供了非常多的3D显示功能.Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括了摄影机.光影.材质 ...
- hdu4126(最小生成树+dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4126 题意:给出一幅3000个点的图,有10000次操作: 求将某条边的权值变大后的最小生成树,最后输 ...
- Catch Up 朋友小聚 - 地道英语 - BBC Learning English BBC英语教学 - 爱思英语网
Catch Up 朋友小聚 - 地道英语 - BBC Learning English BBC英语教学 - 爱思英语网 Catch Up 朋友小聚 分享到: 新浪微博 QQ空间 腾讯微博 微信 更多 ...
- Codeforces Round #254 (Div. 1)-A,B
A:选取两点一边就能够了,非常明显能够想出来... 可是一開始看错题了,sad.... #include<stdio.h> #include<string.h> #includ ...
- jquery下php与ajax的数据交换方式
参考链接:http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2013/0122/11971.html 一.前台传递字符串变量,后台返回字符串变量( ...
- HttpClient 网络优化
HttpClient 网络优化 尽管Android官网推荐在2.3及后续版本中使用HttpURLConnection作为网络开发首选类,但在连接管理和线程安全方面,HttpClient还是具有很大优势 ...
- 【SSH 基础】浅谈Hibernate关系映射(4)
继上篇博客 多对多关联映射(单向) 多对多对象关系映射,须要增加一张新表完毕基本映射. Hibernate会自己主动生成中间表 Hibernate使用many-to-many标签来表示多对多的关联,多 ...