Linux C++线程池实例
想做一个多线程服务器测试程序,因此参考了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++线程池实例的更多相关文章
- java线程池实例
目的 了解线程池的知识后,写个线程池实例,熟悉多线程开发,建议看jdk线程池源码,跟大师比,才知道差距啊O(∩_∩)O 线程池类 package thread.pool2; impor ...
- Java5中的线程池实例讲解
Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活.本文通过一个网络服务器模型,来实践Java5的多线程 ...
- Asp.net 使用线程池实例
实际开发经常会使用线程,如果每次使用都是创建线程.启动线程,然后销毁线程,从性能上来讲,非常占用系统开销,当线程达到一定量的时候会影响程序的运行和处理效率. 使用线程池:好处:线程池是一种多线程处理形 ...
- linux C 线程池(物不可穷也~)
Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1. 线程池介绍 为什么需要线程池??? 目前的大 ...
- 线程池实例:使用Executors和ThreadPoolExecutor
线程池负责管理工作线程,包含一个等待执行的任务队列.线程池的任务队列是一个Runnable集合,工作线程负责从任务队列中取出并执行Runnable对象. java.util.concurrent.ex ...
- 基于linux与线程池实现文件管理
项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...
- Linux C++线程池
.为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...
- Linux下线程池的理解与简单实现
首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...
- JAVA四种线程池实例
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java 1 2 3 4 5 6 7 new Thread(new Runnable() { ...
随机推荐
- spring入门(五) spring mvc+hibernate
核心是让SessionFactory由Spring管理 1.引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework/sp ...
- HTTP基本内容
*********************HTTP基本交互*************************** HTTP请求格式:HTTP 请求由三部分组成:请求行.请求头和请求正文请求行: 请求方 ...
- ABAP术语-Business Connector
Business Connector 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/27/1016379.html XML-based st ...
- frame3.5安装出错
一般是因为禁用了microsoft update,可以在服务里禁用改为手动,之后启动,然后就可以安装
- Tornado异步之-协程与回调
回调处理异步请求 回调 callback 处理异步官方例子 # 导入所需库 from tornado.httpclient import AsyncHTTPClient def asynchronou ...
- JDK6 新特性
JDK6新特性目录导航: Desktop类和SystemTray类 JAXB2实现对象与XML之间的映射 StAX Compiler API 轻量级 Http Server API 插入式注解处理AP ...
- QQ群技术:0成本创建2000人QQ群技巧
群人数,直接关系群权重;于排名,意义非凡;此法靠谱,笔者亲测. 就说这张图,这类关键词,要是没2000人群,不管你多流弊,你是做不上去滴. 于QQ群霸屏,笔者有太多的笔墨,各种排名技巧,阿力推推早前明 ...
- cmd_menu.c
#include <common.h>#include <config.h>#include <command.h> static char cmd_buf[200 ...
- Python基本图形绘制
turtle的一个画布空间最小单位是像素 turtle的绘制窗体:turtle.stup(width,heigth,startx,starty) 四个参数中后两个可选 turtle空间坐标体系:tur ...
- 阿里云异常网络连接-可疑WebShell通信行为的分析解决办法
2018年10月27日接到新客户网站服务器被上传了webshell脚本木马后门问题的求助,对此我们sine安全公司针对此阿里云提示的安全问题进行了详细分析,ECS服务器被阿里云提示异常网络连接-可疑W ...