• disruptor实操作手冊(二)


    多消费者场景


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

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


    一,多个消费者:

    之前的这一行代码是向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

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


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

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




  • 相关阅读:
    Eclipse 插件开发 —— 深入理解查找(Search)功能及其扩展点
    Spring Auto Scanning Components
    SSH架构简单总结
    eclipse进行开发
    jasper ireport create a report with parameters without sql query
    VARCHAR2转换为CLOB碰到ORA-22858错误
    cannot find w3wp.exe in VS
    10 things you should know about NoSQL databases
    Notifications Nagios
    Serializable
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6929220.html
Copyright © 2020-2023  润新知