文档章节

一个简单的线程池模型实现

西昆仑
 西昆仑
发布于 2012/06/13 21:47
字数 763
阅读 827
收藏 7
点赞 2
评论 3

1. 简介

在EPoll通信模型中,我们常常使用如下的处理方法:

就是将触发的事件交给线程去做而EPoll只管接收产生的事件,为了提高效率,我们会使用多线程(因为当事件产生的速度很快,在排队时,我们用多线程去处理,可以加快事件的处理速度),而线程池可以避免程序在响应用户的过程中频繁产生线程创建和销毁,提高程序效率。

2. 基本结构

 

处理流程:
当任务队列中有线程时,各线程中队列中取任务并执行任务
若任务队列中没有任务,各线程阻塞
若有新任务达到,唤醒一个线程,去处理新到达的任务

3. 相关元素

线程类:Thread 基于-lpthread封装了自己的线程类
(在之前的博文中有提过:http://my.oschina.net/myspaceNUAA/blog/61975)
互斥量:基于pthread_mutex_t的封装,Mutex类,用于对资源的互斥访问
信号量:基于pthread_cond_t的封装,Condition类,用于线程的等待和苏醒(没有资源陷入等待状态, 若有资源到达,要唤醒阻塞线程起来开工)
线程池:就是线程容器,任务队列的存放容器,同时将任务队列中的任务派发给线程去执行

 

4. 核心代码
4.1. 线程池启动,就要将指定数量的线程创建好

void start()
{
	for (int i = 0; i < m_nPoolSize; i++)
	{		
	    boost::function<void()>  f;
	    f = boost::bind(&ThreadPool::runInThread, this);
     	    Thread* pTd = new Thread(f,szId);
	    m_pThreads.push_back(pTd);
	    pTd->start();
	}
}

 


4.2 将任务交付给线程池:

/*********************************************************
函数名:run
功能:	向线程池中注入任务,插入到任务队列中
参数:	task 运行任务
**********************************************************/
void run(ThreadPool::Task &task)
{
	MutexLock mutexLock(m_mutex);
	m_tasks.push_back(task);
	m_cond.notify(); //有新资源,要唤醒一个线程去处理任务
}

 

 

 

4.3 如何将Task派发给各线程去执行

 

在线程池创建线程时,每个线程的运行函数都是:ThreadPool::runInThread,也就是说,每个线程通过这个函数从任务队列中取任务并执行,新任务到了后在任务队列中排队,那个线程有空,自然会被唤醒去取任务并执行。

 

void runInThread()
{
   while(m_bRunning)
   {
	if (!m_tasks.empty())
	{
	   ThreadPool::Task task = takeTask();
           if (task)
               task();
        }
   }
}

 

 

 

 5. 测试程序以及测试结果:

#include <iostream>
#include "ThreadPool.h"
using namespace std;

void function(int a, int b)
{
    int sum = a + b;
    cout<<"function: sum is "<<sum<<endl;
}

int main()
{
    ThreadPool threadPool(10, "ThreadPool Of Scott");
    threadPool.start();

    boost::function<void()> f;
    for (int i = 0; i < 20; i++)
    {
	f = boost::bind(function, i, i+1);
	threadPool.run(f); //依次把任务交给线程池
    }

    sleep(1000*60);
    return 0;
}

 

运行结果:

function: sum is 1
function: sum is 3
function: sum is 5
function: sum is 7
function: sum is 9
function: sum is 11
function: sum is 13
function: sum is 15
function: sum is 17
function: sum is 19
function: sum is 21
function: sum is 23
function: sum is 25
function: sum is 27
function: sum is 29
function: sum is 31
function: sum is 33
function: sum is 35
function: sum is 37
function: sum is 39

 

注:模型参考自陈硕MUDUO网络通信库

 

© 著作权归作者所有

共有 人打赏支持
西昆仑

西昆仑

粉丝 137
博文 141
码字总数 102641
作品 0
南京
高级程序员
加载中

评论(3)

西昆仑
西昆仑

引用来自“WILLBeSoSo”的评论

这个是muduo库下的线程池模型吧。。很不错的
是的。。。。
WILLBeSoSo
WILLBeSoSo
这个是muduo库下的线程池模型吧。。很不错的
双子座
双子座
其实这个事情我们一直在做。。。
SOCKET各种模型下并发数量

1、普通的阻塞和非阻塞编程。 利用线程池技术和内存池,SOCKET池技术,基本可以处理一千五百个左右的SOCKET连接,但我们一般使用的机器大约有两M内存,而在不改变线程堆栈的大小情况下,我们...

小报童
2013/03/02
0
0
基于事件的 NIO 多线程服务器

JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程开销的问题,在 NIO 中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个 CPU 的处理能...

恶魔在江湖
2014/03/05
0
0
第十五章:选择正确的线程模型

本章介绍 线程模型(thread-model) 事件循环(EventLoop) 并发(Concurrency) 任务执行(task execution) 任务调度(task scheduling) 线程模型定义了应用程序或框架如何执行你的代码,选择应用程...

李矮矮
2016/09/27
15
0
模仿Tomcat的BIO,NIO线程模型

模仿Tomcat的BIO模型,来一个消息,分配一个线程处理. 则主线程池代码如下 package com.guanjian; import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutorS......

算法之名
07/10
0
0
源码|从串行线程封闭到对象池、线程池

今天讲一个牛逼而实用的概念,。是串行线程封闭的典型应用场景;糅合了对象池技术,但核心实现不依赖于对象池,很容易产生误会。本文从串行线程封闭和对象池入手,最后通过源码分析线程池的核...

猴子007
2017/11/14
0
0
网络-BIO-伪异步I/O

为了解决同步阻塞I/O面临的一个链路需要一个线程处理的问题,后来有人对它的线程模型进行了优化,后端通过一个线程池来处理多个客户端的请求接入,形成客户端个数M:线程池最大线程数N的比例...

xyh12344
2015/12/21
59
0
SEAD架构介绍

由于这个架构没怎么学习,只是简单做一下记录,据说 Cassandra就是用架构实现的 一、传统并发模型的缺点 基于线程的并发 特点: 每任务一线程 直线式的编程 使用资源昂高, context切换代价高...

满小茂
2016/04/15
137
0
gecko框架概述

1 gecko概述 最近在研究metaq消息队列,它里面用到的NIO通信框架是gecko,文档是这么描述的 Gecko是一个Java NIO的通讯组件,它在一个轻量级的NIO框架的基础上提供了更高层次的封装和功能。 ...

乒乓狂魔
2015/12/19
421
2
Dubbo线程模型

线程是每个应用都必须关系的事情,毕竟任何服务器的资源都是有限的,服务线程过少的容易发生阻塞,服务线程过多的话上下文切换的开销又会影响效率,所以合适的线程模型对于一个高性能的应用来...

档滴啷当
2017/12/22
0
0
服务器的实现NIO与BIO

服务器的实现不止有这两种方式。 先谈谈题主说的这两种服务器模型: 1、收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就...

久违了java
2017/09/05
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java 重写排序规则,用于代码层级排序

1.dataList 是个List<Map<String,Object>> 类型的数据,所以比较的时候是冲map中获取数据,并且数据不能为空。 2.dataList 类型是由自己定义的,new Comparator<Map<String,Object>> 也是对应......

轻量级赤影
3分钟前
0
0
分布式大型互联网企业架构!

摘要: 开发工具 1.Eclipse IDE:采用Maven项目管理,模块化。 2.代码生成:通过界面方式简单配置,自动生成相应代码,目前包括三种生成方式(增删改查):单表、一对多、树结构。生成后的代码...

明理萝
4分钟前
0
1
对MFC程序的一点逆向分析:定位按钮响应函数的办法

因为消息响应函数保存在AFX_MSGMAP_ENTRY数组中, 观察nMessage、nCode、nID、pfn利用IDA在rdata段中搜索即可, 在IDA中找到代码段基址0x401000,函数地址0x403140, 在WinDbg中运行!addre...

oready
4分钟前
0
0
阻抗匹配与史密斯(Smith)圆图基本原理

参考:http://bbs.eeworld.com.cn/thread-650695-1-1.html

whoisliang
9分钟前
0
0
maven配置文件分离

一、 简介 遇到很多次别人处理的项目,测试环境,本地开发和线上环境的配置不一样,每一次部署都要重新修改配置文件,提交审核代码,才能打包,非常不方便。 其实相信很多人都知道可以使用m...

trayvon
10分钟前
0
0
MacOS和Linux内核的区别

导读 有些人可能认为MacOS和Linux内核有相似之处,因为它们可以处理类似的命令和类似的软件。甚至有人认为苹果的MacOS是基于linux的。事实上,这两个内核的历史和特性是非常不同的。今天,我...

问题终结者
26分钟前
1
0
SpringBoot | 第八章:统一异常、数据校验处理

前言 在web应用中,请求处理时,出现异常是非常常见的。所以当应用出现各类异常时,进行异常的捕获或者二次处理(比如sql异常正常是不能外抛)是非常必要的,比如在开发对外api服务时,约定了响...

oKong
33分钟前
0
0
mysql高级

一、存储引擎 InnoDB MyISAM 比较 二、数据类型 整型 浮点数 字符串 时间和日期 三、索引 索引分类 索引的优点 索引优化 B-Tree 和 B+Tree 原理 四、查询性能优化 五、切分 垂直切分 水平切分...

丁典
54分钟前
1
0
rsync通过同步服务、系统日志、screen工具

rsync通过后台服务同步 在远程主机中建立一个rsync服务器,在服务器上配置好rsync的各种应用,然后将本机作为rsync的一个客户端连接远程的rsync服务器。 首先在A机器上建立并且配置rsync的配...

黄昏残影
今天
5
0
Spring Cloud Gateway 接口文档聚合实现

在微服务架构下,通常每个微服务都会使用Swagger来管理我们的接口文档,当微服务越来越多,接口查找管理无形中要浪费我们不少时间,毕竟懒是程序员的美德。 由于swagger2暂时不支持webflux 走...

冷冷gg
今天
137
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部