线程池代码(通用版)

线程池代码(通用版)

一、适用场景

    首先,必须明确一点,线程池不是万能的,它有其特定的使用场景。使用线程池是为了减小线程本身的开销对应用性能所产生的影响,但是其 前提是线程本身创建、销毁的开销和线程执行任务的开销相比是不可忽略的 。如果线程本身创建、销毁的开销对应用程序的性能可以忽略不计,那么使用/不使用线程池对程序的性能并不会有太大的影响。

    线程池通常适合以下几种场景:

        ①、单位时间内处理的任务频繁,且任务时间较短

        ②、对实时性要求较高。如果接收到任务之后再创建线程,可能无法满足实时性的要求,此时必须使用线程池。

        ③、必须经常面对高突发性事件。比如Web服务器。如果有足球转播,则服务器将产生巨大冲击,此时使用传统方法,则必须不停的大量创建、销毁线程。此时采用动态线程池可以避免这种情况的发生。

二、代码实现

2.1 头文件

#if !defined(__THREAD_POOL_H__)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <memory.h>
#include <pthread.h>
#include <sys/types.h>

// 布尔类型
typedef int bool;
#define false (0)
#define true  (1)

/* 线程任务链表 */
typedef struct _thread_worker_t
{
	void *(*process)(void *arg);  /* 线程处理的任务 */
	void *arg;                    /* 任务接口参数 */
	struct _thread_worker_t *next;/* 下一个节点 */
}thread_worker_t;

/* 线程池对象 */
typedef struct
{
	pthread_mutex_t queue_lock;   /* 队列互斥锁 */
	pthread_cond_t queue_ready;   /* 队列条件锁 */

	thread_worker_t *head;        /* 任务队列头指针 */
	bool isdestroy;               /* 是否已销毁线程 */
	pthread_t *threadid;          /* 线程ID数组 —动态分配空间 */
	int num;                      /* 线程个数 */
	int queue_size;               /* 工作队列当前大小 */
}thread_pool_t;

/* 函数声明 */
extern int thread_pool_init(thread_pool_t **pool, int num);
extern int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg);
extern int thread_pool_destroy(thread_pool_t *pool);

#endif /*__THREAD_POOL_H__*/

  

2.2 函数实现

 

/*************************************************************
 **功  能:线程池的初始化
 **参  数:
 **    pool:线程池对象
 **    num :线程池中线程个数
 **返回值:0:成功 !0: 失败
 *************************************************************/
int thread_pool_init(thread_pool_t **pool, int num)
{
	int idx = 0;

        /* 为线程池分配空间 */
	*pool = (thread_pool_t*)calloc(1, sizeof(thread_pool_t));
	if(NULL == *pool)
	{
		return -1;
	}

        /* 初始化线程池 */
	pthread_mutex_init(&((*pool)->queue_lock), NULL);
	pthread_cond_init(&((*pool)->queue_ready), NULL);
	(*pool)->head = NULL;
	(*pool)->num = num;
	(*pool)->queue_size = 0;
	(*pool)->isdestroy = false;
	(*pool)->threadid = (pthread_t*)calloc(1, num*sizeof(pthread_t));
	if(NULL == (*pool)->threadid)
	{
		free(*pool);
		(*pool) = NULL;

		return -1;
	}

        /* 依次创建线程 */
	for(idx=0; idx<num; idx++)
	{
		pthread_create(&((*pool)->threadid[idx]), NULL, thread_routine, *pool);
	}

	return 0;
}

  

/*************************************************************
 **功  能:将任务加入线程池处理队列
 **参  数:
 **    pool:线程池对象
 **    process:需处理的任务
 **    arg: process函数的参数
 **返回值:0:成功 !0: 失败
 *************************************************************/
int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg)
{
	thread_worker_t *worker=NULL, *member=NULL;
	
	worker = (thread_worker_t*)calloc(1, sizeof(thread_worker_t));
	if(NULL == worker)
	{
		return -1;
	}

	worker->process = process;
	worker->arg = arg;
	worker->next = NULL;

	pthread_mutex_lock(&(pool->queue_lock));

	member = pool->head;
	if(NULL != member)
	{
		while(NULL != member->next) member = member->next;
		member->next = worker;
	}
	else
	{
		pool->head = worker;
	}

	pool->queue_size++;

	pthread_mutex_unlock(&(pool->queue_lock));
	pthread_cond_signal(&(pool->queue_ready));

	return 0;
}

  

/*************************************************************
 **功  能:线程池的销毁
 **参  数:
 **    pool:线程池对象
 **返回值:0:成功 !0: 失败
 *************************************************************/
int thread_pool_destroy(thread_pool_t *pool)
{
	int idx = 0;
	thread_worker_t *member = NULL;

	if(false != pool->isdestroy)
	{
		return -1;
	}

	pool->isdestroy = true;

	pthread_cond_broadcast(&(pool->queue_ready));
	for(idx=0; idx<pool->num; idx++)
	{
		pthread_join(pool->threadid[idx], NULL);
	}

	free(pool->threadid);
	pool->threadid = NULL;

	while(NULL != pool->head)
	{
		member = pool->head;
		pool->head = member->next;
		free(member);
	}

	pthread_mutex_destroy(&(pool->queue_lock));
	pthread_cond_destroy(&(pool->queue_ready));
	free(pool);
	
	return 0;
}

  

/*************************************************************
 **功  能:线程池各个线程入口函数
 **参  数:
 **    arg:线程池对象
 **返回值:0:成功 !0: 失败
 *************************************************************/
static void *thread_routine(void *arg)
{
	thread_worker_t *worker = NULL;
	thread_pool_t *pool = (thread_pool_t*)arg;

	while(1)
	{
		pthread_mutex_lock(&(pool->queue_lock));
		while((false == pool->isdestroy) && (0 == pool->queue_size))
		{
			pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
		}

		if(false != pool->isdestroy)
		{
			pthread_mutex_unlock(&(pool->queue_lock));
			pthread_exit(NULL);
		}

		pool->queue_size--;
		worker = pool->head;
		pool->head = worker->next;
		pthread_mutex_unlock(&(pool->queue_lock));

                /* 执行队列中的任务 */
		(*(worker->process))(worker->arg);

		free(worker);
		worker = NULL;
	}
}

 

学习版:https://www.cnblogs.com/cthon/p/9085026.html

通用版代码:https://www.cnblogs.com/cthon/p/9097007.html  

难度升级版代码:https://www.cnblogs.com/cthon/p/9085623.html

 

转载于:https://www.cnblogs.com/cthon/p/9097007.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101642.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • c# 看门狗 程序_看门狗制作东西怎么切换

    c# 看门狗 程序_看门狗制作东西怎么切换C#制作简单的看门狗程序这个类实现了程序退出能重启,但是程序停止运行弹出对话框,进程并没有退出却无法重启。希望有好建议处理这个bug的朋友提出你们的宝贵意见。源码如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Diagnostics;usi

  • ES集群搭建详细步骤[通俗易懂]

    ES集群搭建详细步骤[通俗易懂]@系统:*Centos6****ES版本:6.4.0服务器三台172.16.0.8172.16.0.6172.16.0.22部署jdk解压jdk放在/data目录,/data/jdk配置环境变量,/etc/proifle里面加入如下exportJAVA_HOME=/data/jdkexportPATH=$PATH:$JAVA_HOME/binexportCLASS…

    2022年10月13日
  • python autopep8_汽车auto出现错误8怎么解决

    python autopep8_汽车auto出现错误8怎么解决PEP8PEP8–StyleGuideforPythonCodePEPmeansPythonEnhancementProposals.可以理解为Python相关的规范性建议文档,深入学习Python必读。autopep8(github)AtoolthatautomaticallyformatsPythoncodetoconformtothePEP8styleguide.autopep8–in-place–aggressive–a..

  • navicat15激活碼3月最新在线激活

    navicat15激活碼3月最新在线激活,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • 下载安装cygwin_ansys17安装教程详细

    下载安装cygwin_ansys17安装教程详细windows下安装cygwin软件详细过程

    2022年10月31日
  • oracle查询结果替换指定字符串_oracle按字符截取

    oracle查询结果替换指定字符串_oracle按字符截取1、拼接字符串格式一:可以使用”||”来拼接字符串select’拼接’||’字符串’asstrfromdual格式二:通过concat()函数实现selectconcat(‘拼接’,’字符串’)asstrfromdual注:oracle的concat函数只支持两个参数的方法,即只能拼接两个参数,如要拼接多个参数则嵌套使用concat可实现,如:selectconcat(concat(‘拼接’,’多个’),’字符串’)fromdual2.1、截取字符串

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号