IOCP完成端口模拟线程池
IOCP完成端口模拟线程池
- 一,样例介绍
一,样例介绍
生产者-消费者模式是一种非常常见的设计模式,它可以很好地模拟实际编程中的大部分使用场景,而IO完成端口也是用来实现多线程之间的通信,因此,本实例基于该模式完成。
首先,我们需要创建IO完成端口,最后一个参数为0,默认创建的IO完成端口数目就是处理器数目,同时,和要创建一定数目的消费者线程,来处理数据。
//创建1个IO完成端口(最后一个参数为0表示创建处理器个个数的IO完成端口)g_hIoCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);//创建的消费者线程(与IO端口绑定的线程)SYSTEM_INFO si; GetSystemInfo(&si); int nCount = si.dwNumberOfProcessors * 2;for (int i = 0; i < nCount; i++){HANDLE hThread = CreateThread(nullptr, 0, ConsumeThread, 0, 0, 0);CloseHandle(hThread);}
然后创建一个生产者线程,用来生产数据,同时当IO请求完成后,将已完成的IO通知追加到IO完成端口的队列中。
//生产者线程,产生数据HANDLE hThread2 = CreateThread(nullptr, 0, ProductThread, 0, 0, 0);CloseHandle(hThread2);
ConsumeThread实现如下:
//消费者线程
DWORD _stdcall ConsumeThread(LPVOID param)
{DWORD dwData;DWORD dwCmpKey = 0;OVERLAPPED *pOverlapped = NULL;SOverLapped *pOverlappedBuf = nullptr;pInfomation pInfo = nullptr;while (true){if (GetQueuedCompletionStatus(g_hIoCompletionPort, &dwData, &dwCmpKey, &pOverlapped, INFINITE)){if (dwCmpKey && pOverlapped){pOverlappedBuf = CONTAINING_RECORD(pOverlapped, SOverLapped, m_ol);pInfo = pOverlappedBuf->pInfo; //取到我们自定义的数据结构字段std::cout << pInfo->szBuf;delete pInfo;delete pOverlappedBuf;}}}return 0;
}
在这里,我们声明了一个SOverLapped结构体,它里面包含了OVERLAPPED字段,以及一个自定义的消息结构体:
struct SOverLapped
{OVERLAPPED m_ol;pInfomation pInfo;
};
CONTAINING_RECORD宏的作用就是根据结构体类型和结构体中成员变量地址和名称则可求出该变量所在结构体的指针。由此得到我们自定义消息指针。
ProductThread实现如下:
//生产者线程
DWORD _stdcall ProductThread(LPVOID param)
{for (int i = 0; i < 100; i++){SOverLapped *pBuf = new SOverLapped;pInfomation pInfo = new Infomation;pInfo->nLength = i;sprintf_s(pInfo->szBuf, "hello IoCompletionPort--%d \n", i);pBuf->pInfo = pInfo;DWORD dwCmKey = 0;PostQueuedCompletionStatus(g_hIoCompletionPort, 0, (ULONG)&dwCmKey, &(pBuf->m_ol));}return 0;
}
PostQueuedCompletionStatus函数为我们提供了一种方式来与线程池中的所有线程进行通信。当我们终止服务应用程序时,如果各线程和在等待完成端口但是又没有已经完成的IO请求,那么它们将无法被唤醒。此时我们可以通过为线程池中的每个线程都调用一次PostQueuedCompletionStatus,将它们全部唤醒,然后各线程会对GetQueuedCompletionStatus的返回值进行检查,如果发现应用程序正在终止,那么它就可以进行清理工作并正常退出。
IOCP完成端口模拟线程池相关推荐
- 多线程的使用——模拟线程池的实现(2015-12-02 00:14:59)
为什么80%的码农都做不了架构师?>>> 线程池接口: package com.dreyer.pattern.threadPool;/*** @description 线程池接 ...
- java自定义模拟线程池
java 线程池API提供了newCachedThreadPool() newFixedThreadPool(int) 等方法 1 public static ExecutorService newC ...
- python tcp server分包_如何创建线程池来监听tcpserver包python
我试图创建线程池来同时对传入的tcp包执行一些操作.在 我在python3中找不到任何内置线程池.我也读了一些关于multiprocessing.Pool的文章,但是它不支持内存共享.所以我使用Que ...
- Windows核心编程 第十一章 线程池的使用
第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...
- 《Windows via C/C++》学习笔记 —— Windows 线程池
线程池(thread pool),允许有多个线程同时存在,并发执行,并且这些线程受到统一管理. 在Windows Vista中,提供了全新的线程池机制,一般这些线程池中的线程的创建的销毁是由操作系统自 ...
- 「视频版」当线程池溢出之后,程序会奔溃吗?面试突击 007 期
哈喽,大家好,我是老王,欢迎来到第 7 期的 Java 面试突击. 本文的面试题是,当线程池的任务溢出之后,程序会奔溃吗? 这个问题问的是关于线程池的任务数超过线程池的承载能力之后,会出现什么情况? ...
- java callable 线程池_JAVA 线程池之Callable返回结果
本文介绍如何向线程池提交任务,并获得任务的执行结果.然后模拟 线程池中的线程在执行任务的过程中抛出异常时,该如何处理. 一,执行具体任务的线程类 要想 获得 线程的执行结果,需实现Callable接口 ...
- 线程池中线程抛了异常如何处理?
文章目录 1. 模拟线程池抛异常 2. 如何获取和处理异常 方案一:使用 try -catch 方案二:使用Thread.setDefaultUncaughtExceptionHandler方法捕获异 ...
- java线程池_Java 并发编程 线程池源码实战
作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...
- Java 并发编程 -- 线程池源码实战
一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...
最新文章
- 银行背景下分库分表技术选型
- python随机数程序源码_Python 实现随机数详解及实例代码
- Java并发笔记(三)
- BZOJ 3224: Tyvj 1728 普通平衡树【Treap】
- 从php+mysql环境的注入,到整台服务器的沦陷
- pandas后台导出excel_pandas导出Excel表格,银行卡号、身份证号无法正常显示的问题,该怎么解决?...
- SQL Server中的STRING_SPLIT函数
- 洛谷——P2525 Uim的情人节礼物·其之壱
- appscan无法连接到服务器_和平精英无法连接到服务器是怎么回事 最新解决方案...
- yum info 查不到nginx下载info的问题
- 产品配置管理相关通知
- 因为涉嫌歧视女性被开除的那位工程师到底在备忘录上写了什么?
- wd移动硬盘不能识别_wd移动硬盘无法识别
- SVN服务器下载与安装
- StrandHogg漏洞修复
- 涂鸦模组开发(压力传感器HX711)——4. 上报传感器数据给涂鸦模块
- 路透社:特斯拉5月在华汽车订单较4月减少近一半
- word 多级列表的标题操作
- 缺省波特率57600
- html5图钉效果,PS CS5操控变形图钉功能实现任意变换人物造型