C/C++ 原生API实现线程池的方法

 更新时间:2021年11月01日 17:00:00   作者:lyshark  
线程池,简单来说就是有一堆已经创建好的线程,接下来通过本文给大家介绍C/C++ 原生API实现线程池的方法,感兴趣的朋友跟随小编一起看看吧

线程池有两个核心的概念,一个是任务队列,一个是工作线程队列。任务队列负责存放主线程需要处理的任务,工作线程队列其实是一个死循环,负责从任务队列中取出和运行任务,可以看成是一个生产者和多个消费l者的模型。在一些高并发的网络应用中,线程池也是常用的技术。陈硕大神推荐的C++多线程服务端编程模式为:one loop per thread + thread pool,通常会有单独的线程负责接受来自客户端的请求,对请求稍作解析后将数据处理的任务提交到专门的计算线程池。

ThreadPool 线程池同步事件: 线程池内的线程函数同样支持互斥锁,信号控制,内核事件控制,临界区控制.

#include <Windows.h>
#include <iostream>
#include <stdlib.h>

unsigned long g_count = 0;

// --------------------------------------------------------------
// 线程池同步-互斥量同步
void NTAPI TaskHandlerMutex(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
	// 锁定资源
	WaitForSingleObject(*(HANDLE *)Context, INFINITE);

	for (int x = 0; x < 100; x++)
	{
		printf("线程ID: %d ---> 子线程: %d \n", GetCurrentThreadId(), x);
		g_count = g_count + 1;
	}

	// 解锁资源
	ReleaseMutexWhenCallbackReturns(Instance, *(HANDLE*)Context);
}

void TestMutex()
{
	// 创建互斥量
	HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);

	PTP_WORK pool = CreateThreadpoolWork((PTP_WORK_CALLBACK)TaskHandlerMutex, &hMutex, NULL);

	for (int i = 0; i < 1000; i++)
	{
		SubmitThreadpoolWork(pool);
	}

	WaitForThreadpoolWorkCallbacks(pool, FALSE);
	CloseThreadpoolWork(pool);
	CloseHandle(hMutex);

	printf("相加后 ---> %d \n", g_count);
}

// --------------------------------------------------------------
// 线程池同步-事件内核对象
void NTAPI TaskHandlerKern(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
	// 锁定资源
	WaitForSingleObject(*(HANDLE *)Context, INFINITE);

	for (int x = 0; x < 100; x++)
	{
		printf("线程ID: %d ---> 子线程: %d \n", GetCurrentThreadId(), x);
		g_count = g_count + 1;
	}

	// 解锁资源
	SetEventWhenCallbackReturns(Instance, *(HANDLE*)Context);
}

void TestKern()
{
	HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	SetEvent(hEvent);

	PTP_WORK pwk = CreateThreadpoolWork((PTP_WORK_CALLBACK)TaskHandlerKern, &hEvent, NULL);

	for (int i = 0; i < 1000; i++)
	{
		SubmitThreadpoolWork(pwk);
	}

	WaitForThreadpoolWorkCallbacks(pwk, FALSE);
	CloseThreadpoolWork(pwk);

	printf("相加后 ---> %d \n", g_count);
}

// --------------------------------------------------------------
// 线程池同步-信号量同步
void NTAPI TaskHandlerSemaphore(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
	// 锁定资源
	WaitForSingleObject(*(HANDLE *)Context, INFINITE);

	for (int x = 0; x < 100; x++)
	{
		printf("线程ID: %d ---> 子线程: %d \n", GetCurrentThreadId(), x);
		g_count = g_count + 1;
	}

	// 解锁资源
	ReleaseSemaphoreWhenCallbackReturns(Instance, *(HANDLE*)Context, 1);
}

void TestSemaphore()
{
	// 创建信号量为100
	HANDLE hSemaphore = CreateSemaphore(NULL, 0, 100, NULL);

	ReleaseSemaphore(hSemaphore, 10, NULL);

	PTP_WORK pwk = CreateThreadpoolWork((PTP_WORK_CALLBACK)TaskHandlerSemaphore, &hSemaphore, NULL);

	for (int i = 0; i < 1000; i++)
	{
		SubmitThreadpoolWork(pwk);
	}

	WaitForThreadpoolWorkCallbacks(pwk, FALSE);
	CloseThreadpoolWork(pwk);
	CloseHandle(hSemaphore);

	printf("相加后 ---> %d \n", g_count);
}

// --------------------------------------------------------------
// 线程池同步-临界区
void NTAPI TaskHandlerLeave(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
	// 锁定资源
	EnterCriticalSection((CRITICAL_SECTION*)Context);

	for (int x = 0; x < 100; x++)
	{
		printf("线程ID: %d ---> 子线程: %d \n", GetCurrentThreadId(), x);
		g_count = g_count + 1;
	}

	// 解锁资源
	LeaveCriticalSectionWhenCallbackReturns(Instance, (CRITICAL_SECTION*)Context);
}

void TestLeave()
{
	CRITICAL_SECTION cs;
	InitializeCriticalSection(&cs);

	PTP_WORK pwk = CreateThreadpoolWork((PTP_WORK_CALLBACK)TaskHandlerLeave, &cs, NULL);

	for (int i = 0; i < 1000; i++)
	{
		SubmitThreadpoolWork(pwk);
	}

	WaitForThreadpoolWorkCallbacks(pwk, FALSE);
	DeleteCriticalSection(&cs);
	CloseThreadpoolWork(pwk);

	printf("相加后 ---> %d \n", g_count);
}

int main(int argc,char *argv)
{
	//TestMutex();
	//TestKern();
	//TestSemaphore();
	TestLeave();

	system("pause");
	return 0;
}

简单的IO读写:

#include <Windows.h>
#include <iostream>
#include <stdlib.h>

// 简单的异步文本读写
int ReadWriteIO()
{
	char enContent[] = "hello lyshark";
	char deContent[255] = { 0 };

	// 异步写文件
	HANDLE hFileWrite = CreateFile(L"d://test.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	if (INVALID_HANDLE_VALUE == hFileWrite)
	{
		return 0;
	}

	WriteFile(hFileWrite, enContent, strlen(enContent), NULL, NULL);
	FlushFileBuffers(hFileWrite);

	CancelSynchronousIo(hFileWrite);
	CloseHandle(hFileWrite);

	// 异步读文件

	HANDLE hFileRead = CreateFile(L"d://test.txt", GENERIC_READ, 0, NULL, OPEN_ALWAYS, NULL, NULL);
	if (INVALID_HANDLE_VALUE == hFileRead)
	{
		return 0;
	}

	ReadFile(hFileRead, deContent, 255, NULL, NULL);
	CloseHandle(hFileRead);
	std::cout << "读出内容: " << deContent << std::endl;
	return 1;
}


// 通过IO获取文件大小
int GetFileSize()
{
	HANDLE hFile = CreateFile(L"d://test.txt", 0, 0, NULL, OPEN_EXISTING, NULL, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		return 0;
	}

	ULARGE_INTEGER ulFileSize;
	ulFileSize.LowPart = GetFileSize(hFile, &ulFileSize.HighPart);

	LARGE_INTEGER lFileSize;
	BOOL ret = GetFileSizeEx(hFile, &lFileSize);

	std::cout << "文件大小A: " << ulFileSize.QuadPart << " bytes" << std::endl;
	std::cout << "文件大小B: " << lFileSize.QuadPart << " bytes" << std::endl;
	CloseHandle(hFile);

	return 1;
}

// 通过IO设置文件指针和文件尾
int SetFilePointer()
{
	char deContent[255] = { 0 };
	DWORD readCount = 0;

	HANDLE hFile = CreateFile(L"d://test.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, NULL, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		return 0;
	}

	LARGE_INTEGER liMove;

	// 设置移动位置
	liMove.QuadPart = 2;
	SetFilePointerEx(hFile, liMove, NULL, FILE_BEGIN);

	// 移动到文件末尾
	SetEndOfFile(hFile);

	ReadFile(hFile, deContent, 255, &readCount, NULL);
	std::cout << "移动指针后读取: " << deContent << " 读入长度: " << readCount << std::endl;

	CloseHandle(hFile);

	// 设置编码格式
	_wsetlocale(LC_ALL, L"chs");
	setlocale(LC_ALL, "chs");
	wprintf(L"%s", deContent);
}

int main(int argc,char *argv)
{
	// 读写IO
	ReadWriteIO();

	// 取文件长度
	GetFileSize();

	// 设置文件指针
	SetFilePointer();

	return 0;
}

到此这篇关于C/C++ 原生API实现线程池的文章就介绍到这了,更多相关C++实现线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言程序设计50例(经典收藏)

    C语言程序设计50例(经典收藏)

    本篇文章是对C语言程序设计的50个小案例进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C++移动语义介绍与使用讲解

    C++移动语义介绍与使用讲解

    首先,移动语义和完美转发这两个概念是在C++的模板编程的基础上,新增的特性,主要是配合模板来使用。本篇会从C++的值类型,到移动拷贝与移动赋值来理解移动语义与完美转发
    2022-09-09
  • QT利用QPainter绘制三维饼状图

    QT利用QPainter绘制三维饼状图

    这篇文章主要为大家详细介绍了如何利用QPainter实现三维饼状图的绘制,由于Qt中没有三维饼状图的绘制组件,因此只能自行绘制,感兴趣的可以动手尝试一下
    2022-06-06
  • 一道超经典的C++结构体的题目

    一道超经典的C++结构体的题目

    以下小编就为大家介绍一道超经典的关于C++结构体的题目。需要的朋友可以过来参考下
    2013-09-09
  • C/C++时间库chrono的使用总结

    C/C++时间库chrono的使用总结

    std::chrono是C++标准库中的一个组件,用于表示和处理时间,其功能就像是心理学中的感知系统,它可以为我们捕捉、量化并操作抽象的时间概念,这就如同我们的大脑可以理解和感知周围环境的时间流逝一样,这种感知和理解能力是人类进行日常活动所必需的,
    2023-12-12
  • strcpy函数实现简示例命分享

    strcpy函数实现简示例命分享

    这篇文章主要介绍了strcpy函数实现简示例命,需要的朋友可以参考下
    2014-03-03
  • C++的静态成员变量和静态成员函数你了解多少

    C++的静态成员变量和静态成员函数你了解多少

    这篇文章主要为大家详细介绍了C++的静态成员变量和静态成员函数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 关于C++的强制类型转换浅析

    关于C++的强制类型转换浅析

    C++的强制类型转换是我们在日常开发中经常会遇到的,下面这篇文章主要给大家介绍了关于C++强制类型转换的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-09-09
  • C语言实现个人财务管理软件

    C语言实现个人财务管理软件

    这篇文章主要为大家详细介绍了C语言实现个人财务管理软件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Libevent的使用及reactor模型详解

    Libevent的使用及reactor模型详解

    Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,这篇文章主要介绍了Libevent的使用及reactor模型,需要的朋友可以参考下
    2024-03-03

最新评论