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

高速异步缓冲区

林小应

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

你可能感兴趣的:(同步)