Chinaunix
标题:
Java 高性能通讯例子
[打印本页]
作者:
ludejun98
时间:
2004-12-29 16:17
标题:
Java 高性能通讯例子
网络通讯是大家非常常见的问题。
今天我针对项目中遇到的一个实际问题探讨一下高性能通讯模式。
网络通讯中常见到一下情况:线程以循环的方式等待接收信息。
0000>; while(...){
0000>; sleep(...);
0000>;
0000>; accept(waitTime);
0000>; ...
0000>; }
乍看上去这种方式没有什么不妥。其实,这种方式有隐患。
第二行的 sleep周期很难调整。
如果需要最好的响应速度,就需要设置的很小。但是占用CPU就多;
如果需要少占CPU,就要设置的大些,可是响应速度(单位时间接收信息量的峰值)会下降。
参考方案如下:
(一)思路:
1 采用观察者模式替代以前的轮循模式,释放CPU。
2 由于观察者的update函数是阻塞的,所以在update函数中启动单独的线程处理接收到的单元。
3 采用一个缓冲队列临时放数据,专门处理数据的线程通过事件驱动模型(Observer模式支持)进行处理。
4 伪代码如下:
0000>; // 信息接收部分。
0000>; while(...){
0000>; sleep(0);
0000>;
0000>; pdu = accept(waitTime);
0000>; if(pdu!=null){
0000>; queue.push(pdu);
0000>; }
0000>; ...
0000>; }
解释:
1 sleep等待的时限为0,就是说,仅仅在必要的时候可以释放CPU调度时间片,
2 只要CPU不忙,就不会等待。
3 在 accept 函数中采取的方式是不占用CPU的阻塞等待,当前MFC和Java中都只持。
4 等待多长时间以后返回,这个时间对其他进程的影响明显缩小。
5 如果有接收到数据,就放入缓冲区中。
2000>; // 队列,从Observable继承。
2000>; public final class BQueue extends Observable{
2000>;
2000>; // 数据放入缓冲区,就自动通知Observer进行处理。
2000>; public synchronized boolean push(Object ms) {
2000>; // 放入缓冲空间。
2000>; ....
2000>;
2000>; // 这里通知队列的观察者,有数据加入。
2000>; this.setChanged();
2000>; this.notifyObservers();
2000>;
2000>; ....
2000>; }
2000>; }
3000>; // 队列的观察者,实现Observer接口。
3000>; public class SendObserver implements Observer{
3000>;
3000>; public void update(Observable arg0, Object arg1) {
3000>;
3000>; BQueue q = (BQueue)arg0;
3000>; .....
3000>; while(q.size()>;0){
3000>; pdu = q.pop();
3000>;
3000>; // 这里对每个PDU,单独启动一个线程进行处理,可以达到响应速度最快
3000>; BHandler handler = new BHandler(pdu);
3000>; handler.startHandle();
3000>; }
3000>; }
3000>; }
解释:
1 这里对每个数据的处理采用非阻塞的方式:启动一个线程。
2 以完成的测试结果:(本机 单位最差机器代表)
用 LinkedList(链表)做为缓冲队列的数据结构,每秒入队和出队的速度在 亿条量级
从缓冲队列中取出数据后,并启动线程进行处理,不考虑完成时间,可接收的浪涌:百万条量级。
4000>; // 可以处理信息单元的线程。
4000>; public class BHandler implements Runnable{
4000>;
4000>; // 在构造函数中把PDU保存下来,随后等待线程启动把PDU处理完毕。
4000>; private RTCS_CTpdu pduForSend;
4000>; BHandler(RTCS_CTpdu pdu){
4000>; pduForSend = pdu;
4000>; }
4000>;
4000>; public void run(){
4000>; // ... 处理
4000>; .....
4000>; }
4000>;
4000>; public void startHandle(){
4000>; new Thread(this).start();
4000>; }
4000>; }
总结
1 本文主要针对我们常见的一些通讯缓冲机制进行改良的方案。可能尚有不足之处,欢迎大家探讨指正,个人联系方式:ludj@hisunsray.com 卢先生。
2 我部分祝鹏先生曾提出动态调整sleep周期的方案,也很可取,探讨请联系:zhupeng@hisunsray.com
作者:
solaris10
时间:
2004-12-30 13:35
标题:
Java 高性能通讯例子
如果用treemap取代linklist,不知道性能方面是不是会有所提高,
采用缓存机制使性能有了较大提高,但是要注意并发问题。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2