zoukankan      html  css  js  c++  java
  • Singleton模式线程相关的(CC++)

    这种需求的最新发展。

    我需要一个静态类,无论地方,我可以在线程中调用它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
    ", 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

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Node.js理解
    PayPal为什么从Java迁移到Node.js
    移动开发技巧总结
    Flex性能调优相关的一些总结
    Flex组件的生命周期
    Adobe Flash Builder 4.7 新功能详解
    【Django】Cookie
    【Django】路由系统
    【Django】视图系统
    【Django】ORM操作#2
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4755855.html
Copyright © 2011-2022 走看看