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

来源:互联网 发布:查看域名注册信息 编辑:程序博客网 时间:2024/05/21 22:55

最近做一个小程序,要求不难,就是一个有若干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()的方法,发现速度提高很快。以下是我统计出的一个表格:

  采用线程直接启动方式 客户端数量 发送的消息数 最大活动线程 最小活动线程 总时间(秒) 转发消息所花最大时间(秒) 2000 10+1 250 3 18 0.062 2000 3+1 375 3 13 0.047 1000 10+1 240 3 7 0.031 1000 3+1 316 3 9 0.047 500 10+1 254 3 5 0.031 500 3+1 333 3 3 0.032

 

  采用线程池方式启动线程 客户端数量 发送的消息数 最大活动线程 最小活动线程 总时间(秒) 转发消息所花最大时间(秒) 1000 10+1 964 5 291 27.959 1000 3+1 379 5 55 15.991 500 10+1 553 5 64 6.270 500 3+1 457 5 9 6.670

 

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