Disruptor-02 再探
2020-06-09 本文已影响0人
rock_fish
上期回顾
在Disruptor-01 初识中对Disruptor有了初步的认知,大概知道其核心组成元素以及核心运转流程,在所有的组成元素中,EventFactory
作用不甚清晰,这一篇就来弄清楚EventFactory
的作用。
EventFactory什么时候用
我们在代码中,加入一些日志信息
public class LongEventFactory implements EventFactory<LongEvent>
{
public LongEvent newInstance()
{
LongEvent longEvent = new LongEvent();
System.out.println("new Event:" + longEvent.hashCode());
return longEvent;
}
}
public static void main(String[] args) throws InterruptedException {
// Executor that will be used to construct new threads for consumers
Executor executor = Executors.newCachedThreadPool();
// 事件工厂,用于创建event
LongEventFactory factory = new LongEventFactory();
// 指定ringbuf的大小,必须是2的整数倍
int bufferSize = 4;
// 构建一个 Disruptor
Disruptor<LongEvent> disruptor = new Disruptor<>(factory, bufferSize, executor);
System.out.println("..new Disruptor...");
// 给disruptor中添加消费者
disruptor.handleEventsWith(new LongEventHandler());
System.out.println("..handleEventsWith...");
// 启动disruptor
disruptor.start();
System.out.println("..start...");
//-----------万事俱备,只欠消息(消息的生产者投递消息)
// Get the ring buffer from the Disruptor to be used for publishing.
RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
LongEventProducer producer = new LongEventProducer(ringBuffer);
// 跟blockqueue 比对一下
for (long l = 0; l<12; l++)
{
long startAt = System.currentTimeMillis();
producer.publishEvent(l);
long endAt = System.currentTimeMillis();
//System.out.println(endAt-startAt);
//Thread.sleep(1000);
}
}
new Event:801197928
new Event:1495242910
new Event:1711574013
new Event:1631862159
..new Disruptor...
..handleEventsWith...
..start...
通过以上日志信息,可明确在构建Disruptor的时候,会调用LongEventFactory#newInstance
创建对象,队列多大,就预先创建多少个事件对象.
此时我们的疑问是,这里预先创建这些对象什么作用呢?
生产者重复使用预创建的事件对象
通过以下日志信息可以看出,事件对象再循环反复使用;
801197928
1495242910
1711574013
1631862159
----------------LongEvent{value=0}
----------------LongEvent{value=1}
----------------LongEvent{value=2}
----------------LongEvent{value=3}
801197928
1495242910
1711574013
1631862159
----------------LongEvent{value=4}
----------------LongEvent{value=5}
----------------LongEvent{value=6}
----------------LongEvent{value=7}
同时我们会开始留意translateTo
这个方法的作用是,复用对象,仅变更对象中的属性值.
/**
* 复用对象,仅变更对象中的属性值
*/
public class LongEventTranslator implements EventTranslatorOneArg<LongEvent,Long> {
@Override
public void translateTo(LongEvent longEvent, long l, Long aLong) {
System.out.println(longEvent.hashCode());
longEvent.set(aLong);
}
}java
- 第一个入参,是预创建的事件对象
- 第二个参数,是序列号,知识后补
- 第三个参数,是将待发送的消息内容,
方法中关键逻辑是 通过longEvent.set(aLong),将消息内容aLong赋值给longEvent中的long类型变量.
为什么要预创建对象,为什么要复用这些事件对象
- 避免对象的创建和销毁
1.1 减少空间开销(内存)
1.2 减少时间开销(new,GC的时间消耗) - 连续的创建对象,会将对象放置在一段相对连续的内存空间中
2.1 连续内存空间的读写,效率更高