public class Trade {
private String id;//ID
private String name;
private double price;//金额
private AtomicInteger count = new AtomicInteger(0);
}
public class TradeHandler implements EventHandler<Trade>, WorkHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) {
this.onEvent(event);
}
/**
* 具体的消费逻辑
* @param event
*/
@Override
public void onEvent(Trade event) {
System.out.println("消费端获取数据:订单id="+event.getId()+",价格="+event.getPrice());
}
}
一、消息处理器方式
public class Main1 {
public static void main(String[] args) throws Exception {
int BUFFER_SIZE = 1024;
int THREAD_NUMBERS = 4;
/*
* createSingleProducer创建一个单生产者的RingBuffer
* 第一个参数叫EventFactory,从名字上理解就是"事件工厂",其实它的职责就是产生数据填充RingBuffer的区块。
* 第二个参数是RingBuffer的大小,它必须是2的指数倍 目的是为了将求模运算转为&运算提高效率
* 第三个参数是RingBuffer的生产都在没有可用区块的时候(可能是消费者(或者说是事件处理器) 太慢了)的等待策略
*/
final RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(() -> new Trade(), BUFFER_SIZE, new YieldingWaitStrategy());
//创建4个固定线程的线程池
ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS);
//创建SequenceBarrier,充当了Producer和Consumer之间的平衡的角色,或者说定义了Consumer要如何等着
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
//创建消息处理器 构造函数的第三个参数为EventHandler接口的实现类
BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<>(ringBuffer, sequenceBarrier, new TradeHandler());
//这一步的目的就是把消费者的位置信息引用注入到生产者,如果只有一个消费者的情况可以省略
ringBuffer.addGatingSequences(transProcessor.getSequence());
//把消息处理器提交到线程池
executors.submit(transProcessor);
//如果存在多个消费者 那重复执行上面3行代码 把TradeHandler换成其它消费者类
/**
* 通过线程池提交10次数据
*/
Future<?> future= executors.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
long sequence;
for(int i = 0; i < 10; i++){
//返回ringBuffer一个可用区块
sequence = ringBuffer.next();
//给这个区块放入数据
Trade trade = ringBuffer.get(sequence);
//生成ID
trade.setId(UUID.randomUUID().toString());
//设置价格
trade.setPrice(Math.random() * 9999);
//发布这个区块的数据使handler(consumer)可见
ringBuffer.publish(sequence);
}
return null;
}
});
//返回null值,表示处理完成
Object o = future.get();
System.out.println("future.get()得到的结果:" + o);
//等上1秒,等消费都处理完成
Thread.sleep(1000);
//通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
transProcessor.halt();
//终止线程
executors.shutdown();
}
}
二、使用工作池
public class Main2 {
public static void main(String[] args) throws InterruptedException {
int BUFFER_SIZE=1024;
int THREAD_NUMBERS=4;
EventFactory<Trade> eventFactory = new EventFactory<Trade>() {
public Trade newInstance() {
return new Trade();
}
};
RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(eventFactory, BUFFER_SIZE);
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);
//消费者
WorkHandler<Trade> handler = new TradeHandler();
//使用工作池
WorkerPool<Trade> workerPool = new WorkerPool<>(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), handler);
workerPool.start(executor);
//生产8个数据
for (int i = 0; i < 8; i++) {
long seq = ringBuffer.next();
Trade trade = ringBuffer.get(seq);
trade.setPrice(Math.random() * 9999);
trade.setId(UUID.randomUUID().toString());
ringBuffer.publish(seq);
}
Thread.sleep(1000);
//workPool释放资源
workerPool.halt();
executor.shutdown();
}
}