想做一个多线程服务器测试程序,因此参考了github的一些实例,然后自己动手写了类似的代码来加深理解。

目前了解的线程池实现有2种思路:

第一种:

主进程创建一定数量的线程,并将其全部挂起,此时线程状态为idle,并将running态计数为0,等到任务可以执行了,就唤醒线程,此时线程状态为running,计数增加,如果计数达到最大线程数,就再创建一组空闲线程,等待新任务,上一组线程执行完退出,如此交替。

第二种:

采用生成者-消费者模式,主进程作为生成者,创建FIFO队列,在任务队列尾部添加任务,线程池作为消费者在队列头部取走任务执行,这之间有人会提到无锁环形队列,在单生成者单消费者的模式下是有效的,但是线程池肯定是多消费者同时去队列取任务,环形队列会造成挂死。

我的实例采用第二种方式实现,在某些应用场景下,允许一定时间内,任务排队的情况,重复利用已有线程会比较合适。

代码比较占篇幅,因此折叠在下面。

task.h:

 #ifndef TASK_H
#define TASK_H #include <list>
#include <pthread.h> using std::list; struct task {
void (*function) (void *);
void *arguments;
int id;
}; struct work_queue {
work_queue(){
pthread_mutex_init(&queue_lock, NULL);
pthread_mutex_init(&queue_read_lock, NULL);
pthread_cond_init(&queue_read_cond, NULL);
qlen = ;
} ~work_queue() {
queue.clear();
pthread_mutex_destroy(&queue_read_lock);
pthread_mutex_destroy(&queue_lock);
pthread_cond_destroy(&queue_read_cond);
} void push(task *tsk);
task *pull();
void post();
void wait(); private:
int qlen;
list< task * > queue;
pthread_mutex_t queue_lock;
pthread_mutex_t queue_read_lock;
pthread_cond_t queue_read_cond;
}; #endif

task.cpp

#include "task.h"

void work_queue::push(task *tsk) {
pthread_mutex_lock(&queue_lock);
queue.push_back(tsk);
qlen++; pthread_cond_signal(&queue_read_cond);
pthread_mutex_unlock(&queue_lock);
} task* work_queue::pull() {
wait(); pthread_mutex_lock(&queue_lock);
task* tsk = NULL;
if (qlen > ) {
tsk = *(queue.begin());
queue.pop_front();
qlen--; if (qlen > )
pthread_cond_signal(&queue_read_cond);
}
pthread_mutex_unlock(&queue_lock);
return tsk;
} void work_queue::post() {
pthread_mutex_lock(&queue_read_lock);
pthread_cond_broadcast(&queue_read_cond);
pthread_mutex_unlock(&queue_read_lock);
} void work_queue::wait() {
pthread_mutex_lock(&queue_read_lock);
pthread_cond_wait(&queue_read_cond, &queue_read_lock);
pthread_mutex_unlock(&queue_read_lock);
}

threadpool.h

 #ifndef THREAD_POOL_H
#define THREAD_POOL_H #include "task.h"
#include <vector> using std::vector; #define safe_delete(p) if (p) { delete p; p = NULL; } struct threadpool {
threadpool(int size) : pool_size(size)
, thread_list(size, pthread_t())
, queue(NULL)
, finish(false)
, ready() { pthread_mutex_init(&pool_lock, NULL);
} ~threadpool() {
thread_list.clear();
safe_delete(queue);
pthread_mutex_destroy(&pool_lock);
} void init();
void destroy();
static void* thread_run(void *tp); void incr_ready();
void decr_ready();
bool close() const; work_queue *queue; private:
int pool_size;
int ready;
bool finish;
pthread_mutex_t pool_lock;
vector <pthread_t> thread_list;
}; #endif

threadpool.cpp

 /*
* threadpool.cpp
*
* Created on: 2017年3月27日
* Author: Administrator
*/ #include "threadpool.h" void* threadpool::thread_run(void *tp) {
threadpool *pool = (threadpool *) tp;
pool->incr_ready(); while() {
task* tsk = pool->queue->pull();
if (tsk) {
(tsk->function)(tsk->arguments);
delete tsk;
tsk = NULL;
} if (pool->close())
break;
} pool->decr_ready(); return NULL;
} void threadpool::incr_ready() {
pthread_mutex_lock(&pool_lock);
ready++;
pthread_mutex_unlock(&pool_lock);
} void threadpool::decr_ready() {
pthread_mutex_lock(&pool_lock);
ready--;
pthread_mutex_unlock(&pool_lock);
} bool threadpool::close() const {
return finish;
} void threadpool::init() {
queue = new work_queue;
if (!queue) {
return;
} for(int i; i<pool_size; i++) {
pthread_create(&thread_list[i], NULL, threadpool::thread_run, (void *)this);
} while(ready != pool_size) {}
} void threadpool::destroy() {
finish = true; while(ready) {
if(queue) {
queue->post();
}
}
}

main.cpp

 //============================================================================
// Name : thread_pool.cpp
// Author : dancy
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================ #include <iostream>
#include "threadpool.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> using namespace std; void job(void *tsk){
printf("job %-2d working on Thread #%u\n", ((task *)tsk)->id, (int)pthread_self());
} task *make_task(void (*func) (void *), int id) {
task *tsk = new task;
if (!tsk)
return NULL; tsk->function = func;
tsk->arguments = (void *)tsk;
tsk->id = id; return tsk;
} int main() {
threadpool tp();
tp.init(); for(int i=; i<; i++)
tp.queue->push(make_task(&job, i+)); tp.destroy();
printf("all task has completed\n");
return ;
}

以上代码需要在linux下编译,mingw下封装的pthread_t,多了一个void *指针,如果要适配还需要自己再封装一次。

Linux C++线程池实例的更多相关文章

  1. java线程池实例

    目的         了解线程池的知识后,写个线程池实例,熟悉多线程开发,建议看jdk线程池源码,跟大师比,才知道差距啊O(∩_∩)O 线程池类 package thread.pool2; impor ...

  2. Java5中的线程池实例讲解

    Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活.本文通过一个网络服务器模型,来实践Java5的多线程 ...

  3. Asp.net 使用线程池实例

    实际开发经常会使用线程,如果每次使用都是创建线程.启动线程,然后销毁线程,从性能上来讲,非常占用系统开销,当线程达到一定量的时候会影响程序的运行和处理效率. 使用线程池:好处:线程池是一种多线程处理形 ...

  4. linux C 线程池(物不可穷也~)

    Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1.  线程池介绍 为什么需要线程池??? 目前的大 ...

  5. 线程池实例:使用Executors和ThreadPoolExecutor

    线程池负责管理工作线程,包含一个等待执行的任务队列.线程池的任务队列是一个Runnable集合,工作线程负责从任务队列中取出并执行Runnable对象. java.util.concurrent.ex ...

  6. 基于linux与线程池实现文件管理

    项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...

  7. Linux C++线程池

    .为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...

  8. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...

  9. JAVA四种线程池实例

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗?   Java   1 2 3 4 5 6 7 new Thread(new Runnable() {        ...

随机推荐

  1. JNI 和 socket api

    1.JavaVM 和 JNIEnvJNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程 ...

  2. SQL on&where&having

    on.where.having这三个都可以加条件的子句中,on是最先执行,where次之,having最后.有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的.但因为on是先把不符合条件的记录 ...

  3. Python常用模块之json、pickle、random、hashlib、collections

    1.json和pickle json用于字符串和Python数据类型间进行转换pickle用于python特有的类型和python的数据类型间进行转换json和pickle均提供了四种方法dumps, ...

  4. DLL DEF文件编写方法 VC++ 调用、调试DLL的方法 显式(静态)调用、隐式(动态)调用

    DLL 文件编写方法: 1.建立DLL工程 2.声明.定义要导出的函数 BOOL WINAPI InitDlg( HWND hTabctrl,TShareMem* pTshare,CRect* prc ...

  5. 利用百度地图API实现地址和经纬度互换查询

    import json import requests def baiduMap(input_para): headers = { 'User-Agent': 'Mozilla/5.0 (Window ...

  6. php判断某个数是素数的3种方法

    什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.) 方法一: 基本方法,——计数方法. $num = 7; $n = ...

  7. 浅谈linux系统中pdf文件的默认打开方式

    atril.gimp和evince,三者均可以打开application/pdf格式文件.gimp为一款图像处理软件:atril为mate环境下常用的文档查看器:evince为gnome环境下常用的文 ...

  8. 分分钟教你学习GIt

    Git配置: $ git config --global user.name "awen" $ git config --global user.email "awen@ ...

  9. python之三元运算

    三元运算(三目运算):用于较简单的判断(if   else). if True: return s = "aaaa" else: return s = "bbbb&quo ...

  10. python中协程实现的本质以及两个封装协程模块greenle、gevent

    协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源). 为啥说它是一个执行单元,因为 ...