最近在Linux下使用mysql时有时会报查询异常,看网上解决方案是多次并发使用,通过gdb调试也找到问题,主要是上次查询结果集未释放,最终导致如此。
大佬说根本解决方案还是线程池,就去看了线程池的一些内容,记录此篇主要是用于自己cv,怕自己忘记

1、threadPool.cpp

#include "threadPool.h"
void* threadRoutine(void* arg);
threadPool* createPool(int max_thread_num, int max_task_queue_items) {threadPool* pool;pool = (threadPool*)malloc(sizeof(threadPool));if (pool == nullptr) {cout << "线程池创建失败" << endl;goto error_handler;}memset(pool, 0, sizeof(threadPool));pool->max_task_queue_items = max_thread_num;pool->max_task_queue_items = max_task_queue_items;pool->threadArray = (pthread_t*)malloc(sizeof(pthread_t) * max_thread_num);if (pool->threadArray == nullptr) {cout << "工作线程创建失败" << endl;goto error_handler;}memset(pool->threadArray, 0, sizeof(( sizeof(pthread_t) * max_thread_num)));pool->task_head = nullptr;  //任务队列初始化if (pthread_mutex_init(&(pool->mutex), nullptr) != 0) {cout << "互斥锁初始化失败" << endl;goto error_handler;}if (pthread_cond_init(&(pool->task_queue_have_misson), nullptr) != 0) {cout << "条件变量队列为空初始化失败" << endl;goto error_handler;}if (pthread_cond_init(&(pool->task_queue_have_space), nullptr) != 0) {cout << "条件变量队列为满初始化失败" << endl;goto error_handler;}/* 工作线程初始化 */for (int i = 0; i < max_thread_num; i++) {if ((pthread_create(&(pool->threadArray[i]), nullptr, threadRoutine, (void*)pool) != 0)){cout << "工作线程创建失败 " << endl;}}return pool;
error_handler:destroy_pool(pool);return nullptr;
}void* threadRoutine(void* arg) {threadPool* pool = (threadPool*)arg;while (true){pthread_mutex_lock(&pool->mutex);if (pool->task_queue_size == 0) {cout << "任务队列为空,线程" << (unsigned int)pthread_self() << "挂起" << endl;pthread_cond_wait(&pool->task_queue_have_misson, &pool->mutex);}taskQueue* currentWorker = pool->task_head;pool->task_head = pool->task_head->next;pthread_cond_broadcast(&pool->task_queue_have_misson);pool->task_queue_size--;pthread_mutex_unlock(&pool->mutex);cout << "当前线程" << (unsigned int)pthread_self() << "开始工作" << endl;currentWorker->taskFun(currentWorker->arg);cout << "当前线程" << (unsigned int)pthread_self()<< "工作完成" << endl;free(currentWorker);currentWorker = nullptr;}
}void addTask(threadPool* pthis, void* (*taskFun)(void* arg), void* arg) {threadPool* pool = pthis;taskQueue* currentTask = nullptr;pthread_mutex_lock(&pool->mutex);while (pool->max_task_queue_items == pool->task_queue_size) {pthread_cond_wait(&pool->task_queue_have_space, &pool->mutex);}currentTask->arg = arg;currentTask->taskFun = taskFun;currentTask->next = nullptr;/*    新的任务加到任务队列尾部    */taskQueue* tempWorker = nullptr;if(pool->task_head != nullptr){tempWorker = pool->task_head;while (tempWorker->next != nullptr) {tempWorker = tempWorker->next;}tempWorker->next = currentTask;}else {pool->task_head->next = currentTask;}pool->task_queue_size++;pthread_cond_signal(&pool->task_queue_have_misson);free(tempWorker);pthread_mutex_unlock(&pool->mutex);
}int destroy_pool(void* pthis) {threadPool* pool = (threadPool*)pthis;if (pool == nullptr) {return -1;}taskQueue* head = nullptr;/*销毁任务队列*/while (pool->task_head != nullptr){head = pool->task_head;pool->task_head = pool->task_head->next;free(head);}for (int i = 0; i < pool->max_thread_num; i++) {pthread_join(pool->threadArray[i],nullptr);}free(pool->threadArray);pthread_cond_destroy(&pool->task_queue_have_misson);pthread_cond_destroy(&pool->task_queue_have_space);pthread_mutex_destroy(&pool->mutex);return 0;
}

2、threadPool.h

#ifndef __THREAD_POOL_H__
#define __THREAD_POOL_H__
#include <pthread.h>
#include <iostream>
#include <string.h>
using namespace std;
/** 任务队列 **/
struct taskQueue{void* (*taskFun)(void* arg);   //函数指针void* arg;struct taskQueue* next;
};      //想法是一个单链表形式的队列/** 线程池结构 **/
struct threadPool{int max_thread_num;       //最大工作线程数量int max_task_queue_items;     //任务队列最大任务数int task_queue_size;     //当前任务队列任务数taskQueue* task_head;    //任务队列头结点pthread_t* threadArray;        //工作线程数组pthread_cond_t task_queue_have_space;   //任务队列是否满了pthread_cond_t task_queue_have_misson;    //任务队列是否空了pthread_mutex_t mutex;        //互斥锁
};
void addTask(threadPool* pthis, void* (*taskFun)(void* arg), void* arg);
threadPool* createPool(int max_thread_num, int max_task_queue_items);
int destroy_pool(void* pthis);
#endif // !

3、main.cpp

#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include "threadPool.h"#define port 8080
#define max_thread_num 10
#define max_task_queue_items 100void error_message(string message){fputs(message.c_str() , stderr);fputc('\n' , stderr);exit(1);
}void* client_fun(void* arg){int sock = *((int *) arg);char buf[1024];int count = 0;int sendBytes = -1;while(1) {memset(buf, 0, sizeof(buf));if ((count = recv(sock, buf, 1024, 0)) > 0){printf("Received a message from %d: %s\n", sock, buf);/*将数据发给服务器   */if((sendBytes = send(sock, buf, strlen(buf),0)) == -1){perror("send");close(sock);printf("Client %d(socket) write failure:%s!\n", sock,strerror(errno));continue;}                        }else {close(sock);printf("Client %d(socket) has left\n", sock);break;}}printf("\r\n client_server_fun执行完毕\r\n");return nullptr;
}int main(){struct sockaddr_in serv_addr,clnt_addr;int serv_sock, clnt_sock;socklen_t clnt_addr_sz;threadPool* pool = NULL;pool = createPool(max_thread_num, max_task_queue_items);serv_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0 , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(port);if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1){error_message("bind() error");}if(listen(serv_sock, 5) == -1){error_message("listen() error");}while(1){clnt_addr_sz = sizeof(clnt_addr);clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_sz);if(clnt_sock == -1){continue;}printf("clientIp: %s", inet_ntoa(clnt_addr.sin_addr));addTask(pool, client_fun, (void*)&clnt_sock);}return 0;
}

简单实现Linux下线程池相关推荐

  1. linux下线程池实现

    linux下线程池实现 转自:http://blog.csdn.net/lmh12506/article/details/7753952 前段时间在github上开了个库,准备实现自己的线程池的,因为 ...

  2. Linux下线程池(ThreadPool)

    目录 一.线程池相关概念及其优点 二.线程池的实现 一.线程池相关概念及其优点 线程池一种线程使用模式,线程过多会带来这个调度的开销进而影响整体的性能,而线程池是提前准备好了线程等待着管理者进行分配任 ...

  3. linux 下线程池

    基本想法是这样的:       1.预创建的线程通过mutex休眠在线程池中.这样,通过unlock该mutex就可以唤醒该线程了:       2.出于简单性的目标,一个线程池内的所有线程的属性都是 ...

  4. Linux下线程池源码实现

    线程池: 初始化阶段创建有最大数量限制的线程,以及一个线程安全的任务队列,若有任务需要处理,则将任务抛入线程池中,线程池中的的线程就会去处理这个任务. 优点 1.避免峰值压力下,资源耗尽的风险: 2. ...

  5. 谈一谈linux下线程池

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

  6. Linux下线程池概念详解以及代码演示

    线程池 概念 多个线程的组合,但是总数量不会超出池子的限制.是多执行流并发/并行处理,每当任务到来都会从池子里取出一个空闲的线程去进行处理. 产生原因 线程若是不限制数量的创建,在峰值的压力下,线程创 ...

  7. C++ Linux下线程池的实现

    线程池提供设计图 转载于:https://www.cnblogs.com/zhanggaofeng/p/9338601.html

  8. Linux 创建线程 段错误,linux下线程池,出现Segmentation fault (core dumped) 问题

    GDB调试段错误,可以有效快速定位到出错该行. 1.让系统在信号中断造成的错误时产生core文件修改core文件大小,需要su权限:#查看core文件设置 ulimit -a#设置core大小为无限 ...

  9. linux动态线程池--原理,这儿的代码不完整

    本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量.文章的最后,我们 ...

最新文章

  1. IOS固定IP对动态IP用pre-share
  2. opencv 图像上画出目标运动的轨迹_基于opencv的单目和双目标定平台手眼标定
  3. 富士通01018z平板电脑评测_档案扫描好帮手,富士通ix1500无线双面高速扫描仪评测...
  4. python怎么控制小数点位数_谈谈关于Python里面小数点精度控制的问题
  5. Spring框架第一天
  6. java redis工具类_redis Java工具类详解
  7. Rapid7 部分源代码遭泄露,成 Codecov 供应链攻击第四个受害者
  8. VB 中定义FileSystemObject对象,要先添加对象
  9. 如何解决苹果Mac安装Ps错误代码182?
  10. 面向对象类设计的五大原则(一)单一职责原则Single Responsibility Principle
  11. [云原生专题-11]:容器 - 如何构建自己的docker镜像:Docker Dockerfile
  12. C#窗体之整人小程序
  13. python调用按键精灵插件_按键精灵WQM软件使用说明书,资深老师讲解就是详细
  14. 京东热销榜排名第一的运营书籍《运营之光》读后笔记
  15. 迅雷x导入未完成任务失败的解决办法。
  16. 监控摄像机的视频摘要(Video Summarization of Surveillance Cameras)
  17. Anroid中Service详解
  18. 《Redis设计与实现 黄建宏 著》阅读笔记目录(持续更新)
  19. 成绩不高?校园招聘了解一下!春招公司大全!
  20. 子类能访问父类的哪些成员?

热门文章

  1. 2021-2027全球与中国美容淋浴器市场现状及未来发展趋势
  2. matlab 局部寻根,MATLAB算法の二分法全局寻根
  3. C# linq left join
  4. 2021-2025年中国拜勒病治疗行业市场供需与战略研究报告
  5. 如何在所有流媒体服务中搜索电影或电视节目
  6. 机器视觉实验三 工件尺寸和面积测量
  7. 讲述近十几年的房地产
  8. R语言——ggplot2的绘图逻辑
  9. unity Layer CullingMask
  10. Keil uVision4使用总结