想做一个多线程服务器测试程序,因此参考了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. 工具类(为控件设置圆角) - iOS

    为了便于日常开发效率,因此创建了一些小的工具类便于使用.具体 code 如下:声明: /* 为控件添加边框样式_工具类 */ #import <UIKit/UIKit.h> typedef ...

  2. jzoj100029. 【NOIP2017提高A组模拟7.8】陪审团(贪心,排序)

    Description 陪审团制度历来是司法研究中的一个热议话题,由于陪审团的成员组成会对案件最终的结果产生巨大的影响,诉讼双方往往围绕陪审团由哪些人组成这一议题激烈争夺. 小 W 提出了一个甲乙双方 ...

  3. [SCOI2009]windy数(数位DP)

    题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 输入输出格式 输 ...

  4. Sonar安装-Linux[20171227]

    前言     一款不错的代码质量管理工具Sonar 前期准备     官方参考文档 https://docs.sonarqube.org/display/SONAR/Documentation     ...

  5. mysql查看锁等信息SQL

    查看锁等信息,包括锁信息: select "HOLD:",ph.id h_processid,trh.trx_id h_trx_id,trh.trx_started h_start ...

  6. HTML5读取input[type=file]中的图片

    转载 https://blog.csdn.net/fd214333890/article/details/71250488

  7. Ajax知识总结

    一 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法.AJAX 最大 ...

  8. php常见面试(Smarty及相关知识)

    1.Smarty简介: 是一种php模板引擎,它分开了后台程序和前台页面内容,使程序员和美工分工合作.还有其它模版引擎实现同样的目的. 2.Smarty使用: 建立php文件: 包含smarty类文件 ...

  9. ZooKeeper(1)-入门

    一. Zookeeper工作机制 二.Zookeeper特点 三.Zookeeper数据结构 四.Zookeeper应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡

  10. C语言实例解析精粹学习笔记——31

    实例31: 判断字符串是否是回文 思路解析: 引入两个指针变量(head和tail),开始时,两指针分别指向字符串的首末字符,当两指针所指字符相等时,两指针分别向后和向前移动一个字符位置,并继续比较, ...