一个简单的Socket消息转发程序中使用ThreadPool和不使用的性能比对

最近做一个小程序,要求不难,就是一个有若干Client连接到一个Server上,然后Client可以向Server发消息,Server把这个消息存入MySQL,并转发给各个Client 。我的大致思路是:每个Client上启动两个线程,一个ClientRecevieThread负责接收Server传来的消息,另一个ClientSendThread负责将自己的消息发送给Server。然后Server上针对每个连接的Client启动一个ClientThread线程,负责接收这个Client传来的消息,Server上还要启动一个总的线程SendThread,由其负责向所有Client转发消息。在具体实现时:每当有Client连接上Server时,即将其add到一个clientList里面,如果这个Client退出,则再remove掉。在发送消息的过程中,ClientSendThead先将msg发送给Server上的ClientThread,由这个ClientThread纪录下收到的消息的时间,消息的发送者等信息,并将他们一起封装到一个自定义的Message类中,并将这个Message加到一个用LinkedList实现的消息队列msgList的末尾。Server上的SendThread则依次读取msgList中的Message,把他们保存到MySQL中,并将其中的msgContent发送个clientList里面的客户端,做完这些事情后,即msgList.removeFirst()。整个过程如下所示:

 

 这个程序我一开始是用线程池实现的。采用了ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)这种构造方法构造出一个pool,使用pool.execute方法启动各个线程。在我模拟多用户同时登陆并发送消息时,发现采用线程池时,程序的运算速度很慢。后来我又采用直接让线程自己start()的方法,发现速度提高很快。以下是我统计出的一个表格:

 

采用线程直接启动方式
客户端数量发送的消息数最大活动线程最小活动线程总时间(秒)转发消息所花最大时间(秒)
200010+12503180.062
20003+13753130.047
100010+1240370.031
10003+1316390.047
50010+1254350.031
5003+1333330.032

 

 

采用线程池方式启动线程
客户端数量发送的消息数最大活动线程最小活动线程总时间(秒)转发消息所花最大时间(秒)
100010+1964529127.959
10003+137955515.991
50010+15535646.270
5003+1457596.670

 

结果已经很明显了,所以2000用户发消息的线程池模拟我就没做。照理来说,采用线程池应该能提高程序性能才对。但是在这个程序中采用线程池却导致了性能的大幅下降。至于其中原因我现在也不是特别清楚。

好的,下面是一个简单使用C++11的thread类编写的线程池程序: ```c++ #include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <functional> class ThreadPool { public: ThreadPool(size_t num_threads) : stop(false) { for (size_t i = 0; i < num_threads; ++i) { workers.emplace_back([this] { for (;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queue_mutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) { return; } task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } } template<class F> void enqueue(F&& f) { { std::unique_lock<std::mutex> lock(queue_mutex); tasks.emplace(std::forward<F>(f)); } condition.notify_one(); } ~ThreadPool() { { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for (std::thread& worker : workers) { worker.join(); } } private: std::vector<std::thread> workers; std::queue<std::function<void()>> tasks; std::mutex queue_mutex; std::condition_variable condition; bool stop; }; int main() { ThreadPool pool(4); for (int i = 0; i < 8; ++i) { pool.enqueue([i] { std::cout << "Task " << i << " executed." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); }); } return 0; } ``` 这个线程池使用一个任务队列来存储需要执行的任务,每个线程从队列取出任务并执行。当队列为空时,线程会等待新的任务到来。线程池的析构函数会等待所有任务执行完毕后再退出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值