高速异步缓冲区、将同步操作转化成异步、没有“等待返回”的开销——适用于所有次重要的操作

来源:互联网 发布:arm与单片机的区别 编辑:程序博客网 时间:2024/05/16 18:46

高速异步缓冲区

林小应

1.      问题描述

            有一封信要寄出去,你不会傻到自己送过去吧,写上地址、投进街边邮筒就可以了,自己继续干其他事情。

             KFC把送外卖的事情都交给了宅急送。如果自己干,一天还能卖几个鸡翅啊。

         ……

         有些事情,不是非常重要,也不影响后续工作,但又比较耗时的,可以交给专门的人或机构去完成,自己腾出手来继续干其他事。可以很大的提高工作效率。

            计算机程序也是这样,比如要将一些日志送到远程日志主机,或者要将配置数据存到Memcached(简称MC),如果由主线程自己完成,会浪费很多时间在等待返回上。可以起一批线程来负责传送日志、存配置数据等。主线程需要传送日志或者存配置数据到MC时,只需要将动作包装成一个动作对象,丢进公共的容器、就像“邮筒”。一批线程会不断的扫描“邮筒”,只要发现有新的动作对象,就从中取出执行掉。

2.      期望

             将一些不是非常重要,不影响后续工作的动作,包装成动作对象,交给缓冲区完成,就像new一个对象一样简单。

3.      设计原理

             思路:新建一个队列,存储动作对象,再新建一批工作线程来执行对象。客户端有需要执行的动作,只需要封装成动作对象,丢进队列就可以了。

        

         一个缓冲区由N个缓冲队列组成

         一个缓冲队列由一个队列、m工作线程、一个监控线程组成

         队列:用来保存待执行的动作对象

         工作线程:不断扫描队列,发现有新的动作对象加进来,就取出执行掉

         监控线程:监控工作线程的状态,如果发现有线程死掉,就重新启动该工作线程,如果重启十次仍不成功,就重现一个工作线程替换原来的。还负责监控队列执行的情况,如果最近t毫秒(我们配的是100ms)推送进来的动作对象没有执行完,则暂停该缓冲区,后续推送进来的动作对象不入队列,直接执行动作。

         以上变量 n、m、t都是可配置的

 

         抽象的数据模型:

               缓冲区模型:

     上面是一个5*5的缓冲区,就是有5个缓冲队列,每个队列有5个守护线程在不断扫描,一旦发现新的动作对象,就取出执行。

 

4.    用法示例

         动作对象模型:

/** * @author linxy 2012-11-30 * */public abstract class AsynItem {public final long birthTime = System.currentTimeMillis();public abstract boolean launch(); }

       缓冲队列中存放的必须是该类型的动作对象

       动作对象类型为AsynItem,只有一个方法launch,所有推送进来的对象只要实现launch方法就可以了,工作线程拿到动作对象以后,会执行launch方法。

       利用缓冲区保存日志的例子:

      AsynItem item = new AsynItem() {        publicboolean launch() {              client.sendMsg(msg);              returntrue;           }       };       AsynLaunchUtil.asynLaunch (item);

            第一句是new一个动作对象,要执行动作是client.sendMsg(msg);第二句AsynLaunchUtil.asynLaunch (item);是将对象丢进缓冲区。

 

5.    说明

           在我们的系统中,缓冲区在收集日志、保存配置数据到memcached等方面很大的提高了性能,运行稳定。而且通用性很好,调用简单——就像上面只需要两行代码。

 

QQ:346420558

 

 

 

 

原创粉丝点击