高并发服务器-线程池实现(c++版本)

为啥需要线程池?

什么情况可以用:

我们经常会遇到一个队列,其中的消息依赖大量的耗时操作,一个线程从队列拉取完全处理不过来,这时候,就需要我们引入线程池的技术。

什么任务队列不适合用

如果队列的消息是有状态的,不建议用,因为多线程的任务分发是随机的,如果你的任务依赖于前一次处理的结果或者对时序有影响,请从整个系统的设计重新考虑任务队列的设计,将不同业务的数据分配到不同的任务队列,来实现对耗时队列的处理,而不是将有状态的任务到多线程处理,否则不可避免要面临数据共享的多线程竞争问题。

线程池如何设计?

1、线程池需要涉及的数据结构接口

工作线程:其中维持了池结构的成员指针,工作worker线程需要通过池成员指针,来获取任务队列的任务。

class CWorker
{
public:
    CWorker(): m_nExit(0)
    {}
    virtual ~CWorker() {}

    static void* WorkerCallBack(void * p);

public:
    int m_nExit;
    pthread_t m_PID;
    CThreadPool* m_pPool;
};

任务结构,虚函数RunJob,根据实际情况派生该结构并实现对应的任务队列实现处理,可自定义自己的任务队列结构。


class CJobs
{
public:
    CJobs() {};
    virtual ~CJobs() {};

    virtual void RunJobs() = 0;
    static void JobsCallback(CJobs* pJobs) 
    {
        pJobs->RunJobs();
    }
};

线程池,其中包括任务队列,处理工作任务的worker,因为多个线程同时取任务队列,需要一个互斥锁,条件变量来唤醒挂起的线程处理数据


class CThreadPool
{
public:
    CThreadPool();
    virtual ~CThreadPool();

    int CreateThreadPool(int nWorkerNums);

    int PushJobs(CJobs* pJobs);
    int RemoverJobs(CJobs* pJobs);

    list<CWorker*> m_Workers;
    list<CJobs*> m_Jobs;

    pthread_mutex_t m_Mutex;
    pthread_cond_t m_Cond;
};

2、接口实现:

创建线程:


int CThreadPool::CreateThreadPool(int nWorkerNums)
{
    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&m_Cond, &blank_cond, sizeof(m_Cond));

    pthread_mutex_t blank_mutext = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&m_Mutex, &blank_mutext, sizeof(blank_mutext));

    for(int i=0; i<nWorkerNums; i++)
    {
        CWorker *worker = new CWorker();
		if (worker == NULL) {
			assert(0);
			return 1;
		}

		int ret = pthread_create(&worker->m_PID, NULL, &worker->WorkerCallBack, (void *)worker);
		if (ret) {			
			assert(0);
			delete worker;
			return 1;
		}

		worker->m_pPool = this;
        m_Workers.push_back(worker);
    }
}

压入队列:

int CThreadPool::PushJobs(CJobs* pJobs)
{
	pthread_mutex_lock(&m_Mutex);
	m_Jobs.push_back(pJobs);
	pthread_mutex_unlock(&m_Mutex);

	pthread_cond_signal(&m_Cond);
}

线程回调:

void* CWorker::WorkerCallBack(void * p)
{
	class CWorker* pWorker = (CWorker*)p;
	while (!pWorker->m_nExit)
	{
		pthread_mutex_lock(&pWorker->m_pPool->m_Mutex);
		while (pWorker->m_pPool->m_Jobs.empty())
		{
			if(pWorker->m_nExit)
				break;
			pthread_cond_wait(&pWorker->m_pPool->m_Cond, &pWorker->m_pPool->m_Mutex);
		}
		
		CJobs* pJobs = pWorker->m_pPool->m_Jobs.front();
		pWorker->m_pPool->m_Jobs.pop_front();
		pthread_mutex_unlock(&pWorker->m_pPool->m_Mutex);
		
		pJobs->JobsCallback(pJobs);
	}
}

demo的简单测试:

class  CMyjobs :public CJobs
{
private:
	/* data */
public:
	CMyjobs() {}
	virtual ~CMyjobs() {}

	virtual void RunJobs()
	{
		printf("you are right!\n");
	}
};


int main()
{
	CThreadPool pool;
	pool.CreateThreadPool(10);
	CMyjobs myJobs1;
	while (1)
	{
		printf("push\n");
		pool.PushJobs(&myJobs1);
		usleep(100);
	}
	return 0;
}

如果对线程要求高,可以加入无锁队列来实现更加高效的线程池。

线分享到这里。这是最简单版本的线程池实现。

以下是使用epoll和线程池实现高并发服务器C++11代码示例: ```cpp #include <iostream> #include <thread> #include <vector> #include <queue> #include <mutex> #include <condition_variable> #include <sys/epoll.h> #include <unistd.h> #define MAX_EVENTS 100 #define THREAD_POOL_SIZE 10 std::mutex mtx; std::condition_variable cv; std::queue<int> taskQueue; void workerThread() { while (true) { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [] { return !taskQueue.empty(); }); int fd = taskQueue.front(); taskQueue.pop(); // 处理任务,这里可以根据具体需求进行处理 lock.unlock(); // 继续监听其他事件 } } int main() { // 创建epoll句柄 int epoll_fd = epoll_create(1); if (epoll_fd == -1) { std::cerr << "Failed to create epoll" << std::endl; return 1; } // 创建线程池 std::vector<std::thread> threadPool; for (int i = 0; i < THREAD_POOL_SIZE; ++i) { threadPool.emplace_back(workerThread); } // 添加监听事件到epoll句柄 struct epoll_event event; event.events = EPOLLIN; event.data.fd = /* 监听的文件描述符 */; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, /* 监听的文件描述符 */, &event) == -1) { std::cerr << "Failed to add event to epoll" << std::endl; return 1; } // 开始监听事件 struct epoll_event events[MAX_EVENTS]; while (true) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events == -1) { std::cerr << "Failed to wait for events" << std::endl; return 1; } for (int i = 0; i < num_events; ++i) { if (events[i].events & EPOLLIN) { // 处理读事件,将任务添加到任务队列 std::lock_guard<std::mutex> lock(mtx); taskQueue.push(events[i].data.fd); cv.notify_one(); } } } // 清理资源 close(epoll_fd); for (auto& thread : threadPool) { thread.join(); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值