线程池相关

在这里插入图片描述

线程池模块分析

1.main();
创建线程池。
向线程池中添加任务。借助回调处理任务。
销毁线程池。
2.pthreadpool_create();
创建线程池结构体指针。
初始化线程池结构体(N个成员变量)
创建n个任务线程
创建1个管理者线程
失败时销毁开辟的所有空间。(释放)
3.threadpool_thread();
进入子线程回调函数
接收参数 void *arg—>pool结构体
为整个结构体加锁
判断条件变量 – > wait
4.adjust_thread();
循环10s执行一次
进入管理者线程回调函数
接收参数pool结构体
为整个结构体加锁
获取线程池要用到的变量。
task_num,live_num,busy_num
根据既定算法,使用上述三变量,判断是否应该创建,销毁线程池中指定步长的线程
5.threadpool_add();
功能
模拟产生任务
设置回调函数处理任务
内部实现
加锁
初始化任务队列结构体成员。 回调函数function,arg
采用环形队列机制,实现添加任务。
唤醒阻塞在条件变量上的线程
解锁
6.从3.的wait之后继续执行,处理任务
加锁
获取任务处理回调函数,及参数
采用环形队列机制,实现处理任务。借助头指针实现
唤醒阻塞在条件变量上的server
解锁
加锁
改忙线程++
解锁
执行处理任务的线程、
加锁
改忙线程–
解锁
7.创建销毁线程
管理者线程根据既定算法,使用上述三变量,判断是否应该创建,销毁线程池中指定步长的线程
满足创建
pthread_create(); 回调任务函数 live_num++
满足销毁
wait_exit_thr_num = 10
signal给阻塞在条件变量上的线程发送家条件满足信号
跳转至—170 wait阻塞线程会被假信号唤醒。判断:wait_exit_thr_num > 0 pthread_exit();

#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>

#include "threadpool.h"

#define DEFAULT_TIME 10
#define MIN_WAIT_TASK_NUM 10
#define DEFAULT_THREAD_VARY 10
#define true 1
#define false 0

typedef struct{
	void *(*function)(void *);//任务的回调函数
	void *arg;//函数的参数
}thread_pool_task_t;//子线程任务结构体

struct threadpool_t{
	pthread_mutex_t lock;//此结构体为全局变量,所以此锁用于锁住本结构体
	pthread_mutex_t thread_counter;//记录忙状态的锁 -- bust_thr_num

	pthread_cond_t queue_not_full;//给服务器用的条件变量,任务队列不为满,通知客户端
	pthread_cond_t queue_not_empty;//给线程池用的条件变量,任务队列不为空,通知线程

	pthread_t *threads;//存放线程池中每个线程的tid
	pthread_t adjust_tid;//存放管理线程
	threadpool_task_t *task_queue;//任务队列(结构体数组)

	int min_thr_num;//线程池最小线程数
	int max_thr_num;//线程池最大线程数
	int live_thr_num;//当前存活的线程个数
	int busy_thr_num;//忙状态线程个数
	int wait_exit_thr_num;//等待销毁的线程个数

	int queue_front;//task_queue队头
	int queue_rear;//队尾
	int queue_size;//队列中的实际任务数量
	int queue_max_size;//可容纳的任务数量的上限

	int shutdown;//线程池使用状态
};

void *threadpool_thread(void *threadpool);

void *adjust_thread(void *threadpool);

int is_thread_alive(pthread_t tid);
int threadpool_free(threadpool_t *pool);

threadpool_t *threadpool_create(int min_thr_num,int max_thr_num,int queue_max_size)
{
	int i;
	threadpool_t *pool = NULL;

	do{
		if((pool = (threadpool_t *)malloc(sizeof(threadpool_t))) == NULL){
			PRINTF("MALLOC THREADPOLL FAIL");
			break;
		}//线程池分配空间失败

		pool->min_thr_num = min_thr_num;
		pool->max_thr_num = max_thr_num;
		pool->busy_thr_num = 0;
		pool->live_thr_num = min_thr_num;
	    pool->wait_exit_thr_num = 0;
		
		pool->queue_size = 0;
		pool->queue_max_size = queue_max_size;
		pool->queue->front = 0;
		pool->queue->rear = 0;

		pool->shutdown = false;//false表示为不关闭线程池

		pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);
		if(pool->threads == NULL){
			printf("threads malloc fail");
			break;
		}
		memset(pool->threads,0,sizeof(pthread_t)*max_thr_num);//初始化保存tid的数组

		pool->task_queue = (threadpool_task_t *)malloc(sizeof(threadpool_task_t *)*queue_max_size);
		if(pool->task_queue == NULL){
			printf("task_queue malloc fail");
			break;
		}//初始化任务队列

		if(pthread_mutex_init(&(pool->lock),NULL) != 0
			|| pthread_mutex_init(&(pool->thread_counter),NULL) != 0
			|| pthread_cond_init(&(pool->queue_not_empty),NULL) != 0
			|| pthread_cond_init(&(pool->queue_not_full),NULL) != 0)
		{
			printf("init the lock or cond fail");
			break;	
		}//初始化锁

		for(i = 0; i < min_thr_num; i++){
			pthread_create(&(pool->thread[i]),NULL,threadpoll_thread,(void *)pool);
			printf("start thread 0x%x...\n",(unsigned int)pool->threads[i]);
		}//创建线程

		pthread_create(&(pool->adjust_tid),NULL,adjust_thread,(void *)pool);

		return pool;
	}while(0);

	threadpool_free(pool);//前面的代码调用失败,释放存储空间

	return NULL;
}

void *threadpool_thread(void *threadpool)
{
	threadpool_t *pool = (threadpool_t *) threadpool;//接受线程池结构体
	threadpool_task_t task;//定义一个任务结构体

	while(true){
		pthread_mutex_lock(&(pool->lock));

		while((pool->queue_size == 0) && (!pool->shutdown)) {
			printf("thread 0x%x is waiting\n",(unsigned int)pthread_self());
			pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));

			if(pool->wait_exit_thr_num > 0){
				pool->wait_exit_thr_num--;

				if(pool->live_thr_num > pool->min_thr_num){
					printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
					pool->live_thr_num--;
					pthread_mutex_unlock(&(pool->lock));

					pthread_exit(NULL);
				}
			}
		}//queue_size == 0,说明没有任务,调用wait阻塞在该变量上

		if(pool->shutdown){
			pthread_mutex_unlock(&(pool->lock));
			printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
			pthread_detach(pthread_self());//设置线程分离
			pthread_exit(NULL);//终止线程
		}

		/*从任务队列里获取任务*/
		task.function = pool->task->task_queue[pool->queue_front].function;
		task.arg = pool->task_queue[pool->queue_front].arg;

		pool->queue_front = (pool->queue_front + 1) % pool -> queue_max_size;
		pool->queue_size--;

		pthread_cond_broadcast(&(pool->queue_not_full));//通知有新任务可以添加

		pthread_mutex_unlock(&(pool->lock));//任务取出后,马上释放线程池

		/*执行任务*/
		printf("thread 0x%x start working\n",(unsigned int)pthread_self());
		pthread_mutex_lock(&(pool->thread_counter));
		pool->busy_thr_num++;
		pthread_mutex_unlock(&(pool->thread_counter));//忙状态

		(*(task.function))(task.arg); //执行任务的回调函数

		printf("thread 0x%x end working\n",(unsigned int)pthread_self());
		pthread_mutex_lock(&(pool->thread_counter));
		pool->busy_thr_num--;
		pthread_mutex_unlock(&(pool->thread_counter));
	}

	pthread_exit(NULL);
}

void *adjust_thread(void *threadpool)
{
	int i;
	threadpool_t *pool = (threadpool_t *)threadpool;
	while(!pool->shutdown){
		sleep(DEFAULT_TIME); // 定时对线程进行管理

		pthread_mutex_lock(&(pool->lock));
		int queue_size = pool->queue_size;
	    int live_thr_num = poll->live_thr_num;
		pthread_mutex_unlock(&(pool->lock));


		pthread_mutex_lock(&(pool->thread_counter));
	    int busy_thr_num = poll->busy_thr_num;
		pthread_mutex_unlock(&(pool->thread_counter));
	

		if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num){
			pthread_mutex_lock(&(pool->lock));
			int add = 0;

			for(i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY
					&& pool->live_thr_num < pool->max_thr_num; i++){
				if(pool->threads[i] == 0 || is_thread_alive(pool->threads[i])){
					pthread_create(&(pool->thread[i]),NULL,threadpool_thread,(void *)pool);
					add++;
					pool->live_thr_num++;
				}
			}

			pthread_mutex_unlock(&(pool->lock));
		}//增加线程数

		if((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num){
			pthread_mutex_lock(&(pool->lock));
			pool->wait_exit_thr_num = DEFAULT_THREAD_VARY; //要销毁的线程数
			pthread_mutex_unlock(&(pool->lock));

			for(i = 0; i < DEFAULT_THREAD_VARY; i++){
				pthread_cond_signal(&(pool->queue_not_empty));
			}//通知空闲状态的线程,让他们自行终止
		}
	}
	
	return NULL;
}

int threadpool_add(threadpool_t *pool,void *(*function)(void *)arg,void *arg)
{
	pthread_mutex_lock(&(pool->lock));

	while((pool->queue_size == pool->queue_max_size) && !(pool->shutdown)) {
		pthread_cond_wait(&(pool->queue_not_full),&(pool->lock));
	}//队列已满,调wait阻塞

	if(pool->shutdown) {
		pthread_cond_broadcast(&(pool->queue_not_empty));
		pthread_mutex_unlock(&(pool->lock));
		return 0;
	}//关闭线程

	if(pool->task_queue[pool->queue_rear].arg != NULL) {
		pool->task_queue[pool->queue_rear].arg = NULL;
	}//清空工作线程调用的回调函数的参数arg

	pool->task_queue[pool->queue_rear].function = function;
	pool->task_queue[pool->queue_rear].arg = arg;
	pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;//模拟环形
	pool->queue_size++;

	pthread_cond_signal(&(pool->queue_not_empty));
	pthread_mutex_unlock(&(pool->lock));

	return 0;
}

int threadpool_destroy(threadpool_t *pool)
{
	int i;
	if(pool == NULL){
		return -1;
	}
	pool->shutdown = true;

	pthread_join(pool->adjust_tid,NULL);//销毁管理线程

	for(i = 0; i < pool->live_thr_num; i++){
		pthread_cond_broadcast(&(pool->queue_not_empty));
	}
	for(i = 0; i < pool->live_thr_num; i++){
		pthread_join(pool->threads[i],NULL);
	}
	
	threadpool_free(pool);

	return 0;
}

int threadpool_free(threadpool_t *pool)
{
	if(pool == NULL)
		return -1;

	if(pool->task_queue)
		free(task_queue);

	if(pool->threads){
		free(pool->threads);
		pthread_mutex_lock(&(pool->lock));
		pthread_mutex_destroy(&(pool->lock));
		pthread_mutex_lock(&(pool->thread_counter));
		pthread_mutex_destroy(&(pool->thread_counter));
		pthread_cond_destroy(&(pool->queue_not_empty));
		pthread_cond_destroy(&(pool->queue_not_full));
	}
	free(pool);
	pool = NULL;

	return 0;
}

void *process(void *arg)
{
	printf("thread 0x%x working on task %d\n",(unsigned int)pthread_self(),(int)arg);
	sleep(1);
	printf("task %d is end\n",(int)arg);

	return NULL;	
}

int main()
{
	threadpool_t *thp = threadpool_create(3,100,100);//创建线程池
	printf("pool inited");

	int num[20],i;
	for (i = 0; i < 20; i++){
		num[i] = i;
		printf("add task %d\n",i);

		threadpool_add(thp,process,(void*)&num[i]);//向线程池添加任务
	}

	sleep(10);//等待子线程完成任务
	threadpool_destroy(thp);//销毁线程池

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,线程池是一种管理和复用线程的机制,可以提高多线程程序的效率和性能。以下是几个与Java线程池相关的最佳实践: 1. 使用Executors类创建线程池:Java提供了Executors类来创建不同类型的线程池。根据实际需求选择适当的线程池类型,如FixedThreadPool、CachedThreadPool、SingleThreadExecutor等。 2. 控制线程池的大小:线程池的大小应根据系统资源和任务特性进行调整。如果任务是CPU密集型的,线程数应与CPU核心数相近;如果是IO密集型的,可以适当增加线程数。 3. 设置合适的队列容量:线程池中的任务队列用于存放待执行的任务。如果任务量大于线程池处理能力,队列容量应设置得足够大,以避免任务丢失或拒绝执行。 4. 使用合适的拒绝策略:当线程池无法处理新提交的任务时,可以使用合适的拒绝策略来处理。常见的拒绝策略包括AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy和DiscardPolicy。 5. 谨慎使用无限线程池:CachedThreadPool是一个无限线程数的线程池,可以根据需要自动创建和回收线程。但过多的线程可能会导致系统负载过高,因此需要谨慎使用。 6. 使用合适的线程命名:为线程池中的线程设置有意义的名称,可以方便调试和日志记录。 7. 考虑任务的优先级:Java线程池支持设置任务的优先级。如果有任务需要优先执行,可以设置较高的优先级。 8. 及时关闭线程池:当不再需要线程池时,应及时关闭以释放资源。可以使用shutdown()方法平缓关闭线程池,或使用shutdownNow()方法立即关闭线程池。 以上是一些常见的Java线程池的最佳实践,根据具体场景和需求,可以进行适当调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值