架构师养成记--16.disruptor并发框架中RingBuffer的使用
很多时候我们只需要消息中间件这样的功能,那么直需要RinBuffer就可以了。
入口:
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- import com.lmax.disruptor.BatchEventProcessor;
- import com.lmax.disruptor.EventFactory;
- import com.lmax.disruptor.RingBuffer;
- import com.lmax.disruptor.SequenceBarrier;
- import com.lmax.disruptor.YieldingWaitStrategy;
- 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 EventFactory<Trade>() {
- @Override
- public Trade newInstance() {
- return new Trade();
- }
- }, BUFFER_SIZE, new YieldingWaitStrategy());
- //创建线程池
- ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS);
- //创建SequenceBarrier
- SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
- /****************** @beg 消费者消费数据 2017-1-11******************/
- //创建消息处理器
- BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<Trade>(
- ringBuffer, sequenceBarrier, new TradeHandler());
- //这一步的目的就是把消费者的位置信息引用注入到生产者 如果只有一个消费者的情况可以省略
- ringBuffer.addGatingSequences(transProcessor.getSequence());
- //把消息处理器提交到线程池
- executors.submit(transProcessor);
- /****************** @end 消费者消费数据 2017-1-11******************/
- //如果存在多个消费者 那重复执行上面3行代码 把TradeHandler换成其它消费者类
- /****************** @beg 生产者生产数据 2017-1-11******************/
- Future<?> future= executors.submit(new Callable<Void>() {
- @Override
- public Void call() throws Exception {
- long seq;
- for(int i=0;i<10;i++){
- seq = ringBuffer.next();//占个坑 --ringBuffer一个可用区块
- ringBuffer.get(seq).setPrice(Math.random()*9999);//给这个区块放入 数据
- ringBuffer.publish(seq);//发布这个区块的数据使handler(consumer)可见
- }
- return null;
- }
- });
- /****************** @end 生产者生产数据 2017-1-11******************/
- future.get();//等待生产者结束
- Thread.sleep(1000);//等上1秒,等消费都处理完成
- transProcessor.halt();//通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
- executors.shutdown();//终止线程
- }
- }
消费者:
- import java.util.UUID;
- import com.lmax.disruptor.EventHandler;
- import com.lmax.disruptor.WorkHandler;
- public class TradeHandler implements EventHandler<Trade>, WorkHandler<Trade> {
- @Override
- public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
- this.onEvent(event);
- }
- @Override
- public void onEvent(Trade event) throws Exception {
- //这里做具体的消费逻辑
- event.setId(UUID.randomUUID().toString());//简单生成下ID
- System.out.println(event.getId());
- }
- }
数据对象:
- import java.util.concurrent.atomic.AtomicInteger;
- public class Trade {
- private String id;//ID
- private String name;
- private double price;//金额
- private AtomicInteger count = new AtomicInteger(0);
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public double getPrice() {
- return price;
- }
- public void setPrice(double price) {
- this.price = price;
- }
- public AtomicInteger getCount() {
- return count;
- }
- public void setCount(AtomicInteger count) {
- this.count = count;
- }
- }
架构师养成记--16.disruptor并发框架中RingBuffer的使用的更多相关文章
- 架构师养成记--15.Disruptor并发框架
一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...
- 架构师养成记--35.redis集群搭建
前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...
- 架构师养成记--10.master-worker模式
master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...
- 架构师养成记--8.Queue
一.ConcurrentLinkedQueue 是一个适合在高并发场景下,无锁,无界的,先进先出原则.不允许为null值,add().offer()加入元素,这两个方法没区别:pull().peek( ...
- 架构师养成记--32.Redis高级(安全 主从复制)
Redis高级命令及特性 keys * 返回满足的所有键值(*表示模糊匹配) exists 是否存在指定的key(返回1表示存在,0表示不存在) expire 设置某个key的过期时间,使用ttl查看 ...
- 架构师养成记--29.redis开篇
主要有从下几点讲解 NOSQL(Redis) 简介.redis安装与部署 Redis基础事件类型详解 Redis高级命令 Redis与java的使用 Redis集群搭建 Redis集群与spring的 ...
- 架构师养成记--21.netty编码解码
背景 作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程.接收到编码后的数据就需要解码,还原传输的数据. 代码 工厂类 import io.netty.han ...
- 架构师养成记--19.netty
一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...
- 架构师养成记--17.disrunptor 多生产者多消费者
入口: import java.nio.ByteBuffer; import java.util.UUID; import java.util.concurrent.CountDownLatch; i ...
随机推荐
- [leetcode]134. Gas Station加油站
There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. Y ...
- MySqlDBHelper
代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Syste ...
- DART: a fast and accurate RNA-seq mapper with a partitioning strategy DART:使用分区策略的快速准确的RNA-seq映射器
DART: a fast and accurate RNA-seq mapper with a partitioning strategyDART:使用分区策略的快速准确的RNA-seq映射器 Abs ...
- 本周MySQL官方verified/open的bug列表(11月15日至11月21日)
本周MySQL verified的bug列表(11月15日至11月21日) 1. Bug #70923 Replication failure on multi-statement INSERT ...
- 5 CrawlSpider操作
CrawlSpider 提问:如果想要通过爬虫程序去爬取"糗百"全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Reques ...
- break,continue以及pass的使用
1.break是提前结束循环 for i in range(1,100): if i%2 == 0: print("wrong") break#直接结束循环,并且不打印下面的pri ...
- js 中的 2 与 "2"
case1: "15" * 2 结果:30 case2: 2 * "15" 结果:30 case3: "2" * "15" ...
- WIP and COST Frequently Used Troubleshooting Scripts (Doc ID 105647.1)
Applies to: Oracle Work in Process - Version 10.7.16.1 to 12.1 [Release 10.7 to 12.1] Information in ...
- Centos 下安装tomcat多实例
基础环境及JDK就不多说了,下面的目录结构以如下为准: 根目录-apps根目录-apps--tomcat根目录-apps--ins1根目录-apps--ins2 =================== ...
- kubernetes yaml
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Deployment #指定创建资源的角色/类型 metadata: #资源的元数据/属性 ...