disruptor实操作手册(二)

多消费者场景


上一篇文章介绍了如何构建一个简单的disruptor工程之后,应该有相当一部分客官骂娘了,确实这样的范例在其它地方多的是。

从这篇开始,介绍一些不一样的东西。


一,多个消费者:

之前的这一行代码是向disruptor中注入一个消费者

disruptor.handleEventsWith(new LongEventHandler() );

在实际工作中,我们并不会仅仅使用一个消费者来执行任务,如果是这样的话,也就几乎没有什么必要来使用disruptor了。

LongEventHandler[] longEventHandlers = {new LongEventHandler(),new LongEventHandler(),new LongEventHandler()};
disruptor.handleEventsWith(longEventHandlers);

将之前那行代码替换成这两句,即可一下注入三个消费者。

运行一下看看,三个消费者将所有的数据都处理了一遍。

2015-06-04 23:28:24,334 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理0
2015-06-04 23:28:24,334 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理0
2015-06-04 23:28:24,334 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理0
2015-06-04 23:28:24,355 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理0
2015-06-04 23:28:24,355 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理0
2015-06-04 23:28:24,356 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理0
2015-06-04 23:28:25,333 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理1
2015-06-04 23:28:25,338 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理1
2015-06-04 23:28:25,341 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理1
2015-06-04 23:28:25,353 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理1
2015-06-04 23:28:25,358 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理1
2015-06-04 23:28:25,361 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理1
2015-06-04 23:28:26,333 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理2
2015-06-04 23:28:26,333 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理2
2015-06-04 23:28:26,333 INFO [com.xuyang.test.disruptor.LongEventHandler] batch开始处理2
2015-06-04 23:28:26,354 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理2
2015-06-04 23:28:26,354 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理2
2015-06-04 23:28:26,354 INFO [com.xuyang.test.disruptor.LongEventHandler] batch结束处理2

如果你愿意,当然也可以使用一个循环语句一下子注入一万个。

看到这里大家是不是会觉得更坑爹了。谁会让一堆消费者把所有的事情都全部做一遍。确实,我写到这里也觉得很坑爹。

那么我们再换一下看看。


二,多个不同的消费者

EventHandler[] eventHandlers = {new LongEventHandler(),new SecondEventHandler()};
disruptor.handleEventsWith(eventHandlers);
我们向disruptor中注入两个不同的消费者。(实例中 SecondEventHandler 代码跟 LongEventHandler 完全一样,我就不贴了)

运行一下

2015-06-04 23:34:11,357 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者开始处理0
2015-06-04 23:34:11,357 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者开始处理0
2015-06-04 23:34:11,378 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者结束处理0
2015-06-04 23:34:11,378 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者结束处理0
2015-06-04 23:34:12,357 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者开始处理1
2015-06-04 23:34:12,357 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者开始处理1
2015-06-04 23:34:12,378 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者结束处理1
2015-06-04 23:34:12,381 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者结束处理1
2015-06-04 23:34:13,357 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者开始处理2
2015-06-04 23:34:13,357 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者开始处理2
2015-06-04 23:34:13,378 INFO [com.xuyang.test.disruptor.LongEventHandler] 第一个消费者结束处理2
2015-06-04 23:34:13,378 INFO [com.xuyang.test.disruptor.SecondEventHandler] 第二个消费者结束处理2

这样看来,好像有一些意义了,两个不同的消费者处理所有的事件发送的数据。

在实际生产中,是会有这样的场景的。比如用户需要我们砌墙,现在就可以让搬砖的和糊墙的同时来干活儿了。

到这里可能有的同学又有疑问了,如果我的工作就是糊墙呢,总不能让雇佣的十个糊墙工把所有的墙都糊一遍吧,要让他们一人糊一个才好。

嗯,这也是我刚开始使用disruptor这个工具所期望的事情。


三,相同功能的消费者同时工作

来看我这文章的你们一定都是不喜欢看源码的家伙,也许你们也搜索了网络,可能看到了下面这样的解决方案。


3.1,首先定义一个带工号的糊墙工

public class youdaoliEventHandler implements EventHandler<LongEvent> {
	private static final Logger LOG =  LoggerFactory
			.getLogger(youdaoliEventHandler.class);
	
	private long ordinal; //当前消费线程的编号,需要指定
	private long numberOfConsumers; //总共多少个消费者
	
	public youdaoliEventHandler(long order,long number){
		ordinal = order;
		numberOfConsumers = number;
	}
	
	@Override
	public void onEvent(LongEvent longEvent, long sequence, boolean endOfBatch)
			throws Exception {
		if ((sequence % numberOfConsumers) == ordinal) {
		//这是我的菜,开始业务处理
			boolean chk = true;
			long l = longEvent.getValue();
			LOG.info("第"+ordinal+"糊墙工开始处理糊墙" + l + "");
			Date dtStart = new Date();
			
			while(chk){
				Date dt = new Date();
				if(dt.getTime() - dtStart.getTime() >=20){
					chk = false;
					LOG.info("第"+ordinal+"糊墙工开始糊墙结束" + l + "");
				}
			}
		}
		
	}

}

将雇来的三个糊墙工编号之后,让他们开始工作

disruptor.handleEventsWith(new youdaoliEventHandler(0,3),new youdaoliEventHandler(1,3),new youdaoliEventHandler(2,3));

运行一下看看

2015-06-04 23:58:33,537 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第0糊墙工开始处理糊墙0
2015-06-04 23:58:33,558 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第0糊墙工开始糊墙结束0
2015-06-04 23:58:34,535 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第1糊墙工开始处理糊墙1
2015-06-04 23:58:34,555 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第1糊墙工开始糊墙结束1
2015-06-04 23:58:35,539 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第2糊墙工开始处理糊墙2
2015-06-04 23:58:35,560 INFO [com.xuyang.test.disruptor.youdaoliEventHandler] 第2糊墙工开始糊墙结束2

哇,满足了你们的期望。

一切看上去都好有道理,我竟然无言以对。

我不会告诉你们,事实上我在一个项目中就是这么使用的,一切运行安好。

但是,disruptor的画风不会是这么农业重金属的。


3.2,下面才是正确的画风。

首先实现一个 WorkHandle 类

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.lmax.disruptor.WorkHandler;

public class FirstWorkEventHandler implements WorkHandler<LongEvent> {
	private static final Logger LOG =  LoggerFactory
			.getLogger(FirstWorkEventHandler.class);
	@Override
	public void onEvent(LongEvent longEvent)
			throws Exception {
		boolean chk = true;
		long l = longEvent.getValue();
		LOG.info("糊墙工开始处理" + l + "");
		Date dtStart = new Date();
		
		while(chk){
			Date dt = new Date();
			if(dt.getTime() - dtStart.getTime() >=20){
				chk = false;
				LOG.info("糊墙工结束处理" + l + "");
			}
		}
	}

}
注入三个WorkHandle消费者到disruptor中

disruptor.handleEventsWithWorkerPool(new FirstWorkEventHandler(),new FirstWorkEventHandler(),new FirstWorkEventHandler());
	
启动看看

2015-06-05 00:08:48,120 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工开始处理0
2015-06-05 00:08:48,142 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工结束处理0
2015-06-05 00:08:49,118 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工开始处理1
2015-06-05 00:08:49,138 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工结束处理1
2015-06-05 00:08:50,119 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工开始处理2
2015-06-05 00:08:50,139 INFO [com.xuyang.test.disruptor.FirstWorkEventHandler] 糊墙工结束处理2

你不需要给他们编号,三个糊墙工自觉的有条不紊的工作着。


------------------------------------------------------------

我知道你们还想了解盖一座房子要怎么安排工人,明天我会透露更多的信息。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值