简单实现Linux下线程池

最近在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 100

void 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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值