【校招 --阶段一 系统编程】线程池

41 篇文章 1 订阅

池化思想:线程池,字符串常量池,数据库连接池
提高资源的利用率
在这里插入图片描述
说明:

  • 当来了任务时sever将任务指派给线程池,由线程完成任务工作
  • sever是从网络中读取任务,而线程池负责消化任务,两组线程就需要任务对列将他门连接起来
  • sever负责将任务塞到任务队列中,将指派给特定的线程

一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着
监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<queue>
using namespace std;
class test {
private:
	int base;
public:
	//bool isempty(){
	//return q.size()==0;
	//}
	test() {}
	test(int a) :base(a) {}
	void run() {


		cout << "test is running。。" << base << "线程id:" << pthread_self() << endl;
	}
	~test() {}
};
class ThreadPool {
private:
	queue<test*> q;
	int cap;//线程池数量
	pthread_mutex_t lock;
	pthread_cond_t cond;
	bool quit;//线程突出
public:
	bool isempty() {
		return q.size() == 0;
	}
	ThreadPool(int cap_) :cap(cap_), quit(false)
	{}
	void Init() {
		pthread_mutex_init(&lock, NULL);
		pthread_cond_init(&cond, NULL);
		pthread_t t;
		for (int i = 0; i < cap; i++) {

			pthread_create(&t, NULL, thread_running, (void*)this);

		}
	}

	void Lock() {
		pthread_mutex_lock(&lock);
	}
	void UnLock() {
		pthread_mutex_unlock(&lock);
	}
	void Waitcond() {
		pthread_cond_wait(&cond, &lock);//若没有直接阻塞自己
	}
	void threadswakeup() {

		pthread_cond_broadcast(&cond);//唤醒所有的线程
	}
	bool Quit() {
	
		return quit;
	}
	static void* thread_running(void* rid) {
		ThreadPool* this_d = (ThreadPool*)rid;
		while (!this_d->Quit()) {//检测是否达到线程退出条件
			//pthread_mutex_lock(&lock);
			this_d->Lock();
			while (!this_d->Quit() && this_d->isempty()) {//检测有没有任务来
				//这里检测quit因为在线程退出后还会唤醒线程,要保证线程不退出才能接到任务
			//pthread_cond_wait(&cond);//若没有直接阻塞自己
				this_d->Waitcond();
			}
			test t;
			if (!this_d->Quit() && !this_d->isempty()) {

				this_d->out(t);//提取出任务
			}//只有保证线程不退出才能拿任务
			t.run();//执行任务在任务类中执行
			this_d->UnLock();
			//pthread_mutex_unlock(&lock);
		}

	}
	void put(test& t) {
		pthread_mutex_lock(&lock);
		q.push(&t);
		pthread_mutex_unlock(&lock);
		pthread_cond_signal(&cond);;
	}
	void threadquit() {
		if (!isempty()) {//任务队列中有任务不能线程不能退出
			return;
		}
		quit = true;//线程退出条件
		threadswakeup();
	}
	void out(test& t) {
		test* a = q.front();
		t = *a;
		q.pop();

	}
	~ThreadPool() {

		pthread_mutex_destroy(&lock);
		pthread_cond_destroy(&cond);

	}
};
int main() {
	ThreadPool* td = new ThreadPool(10);

	td->Init();
	while (1) {

		int s = rand() % 10 + 1;
		test t(s);
		td->put(t);
		sleep(1);
	}

	return 0;
}

说明:

为什么定义任务队列要定义成这样queue<test*> q;?
因为在任务复制时一定回调test的默认拷贝函数,或者赋值语句不管用什么方式都是要把任务整体拷贝一份。当任务量很大时,效率就成了问题,所以这里用指针效率就是恒定的。
当任务队列没任务时要让特定线程等(死循环,直到检测到任务队列不为空为止),直到有任务来,接着唤醒线程池线程来执行任务
为什么在函数thread_running()前要加static?
因为当thread_running当作成员函数,而内部成员函数在编译时都默认加一个this指针作为第一个参数,一旦this指针做第一个参数这个函数就成了两个参数第一个this指针,第二个void*因为当创建线程时int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(start_routine)(void), void arg);第三个参数回调函数void (start_routine)(void),只有一个参数void,当thread_running时成员函数时会传入两个参数,所以在该函数要加static,表明该函数属于该类 不具有this指针,static函数无法放问成员函数,也无法找到某一个对象的成员函数,所以在创建线程时要将this指针传进来。
pthread_create(&t, NULL, thread_running, (void
)this);

在这里插入图片描述
十个线程组成的线程池依次执行任务。

什么会按顺序指派给线程?线程实在等待cond排的对 为什么一次之唤醒线程?当一次唤醒所有线程,首先执行次序会不固定,接着一次唤醒所有线程会造成惊群效应
惊群效应请参考这里

线程池存在的价值:

1 有任务,立马有线程进行服务,省掉了线程创建
2 有效防止sever中线程过多,导致系统过载的问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值