Java 并发框架Disruptor(七)
Disruptor VS BlockingQueue的压测对比:
import java.util.concurrent.ArrayBlockingQueue; public class ArrayBlockingQueue4Test { public static void main(String[] args) {
final ArrayBlockingQueue<Data> queue = new ArrayBlockingQueue<Data>(100000000);
final long startTime = System.currentTimeMillis();
//向容器中添加元素
new Thread(new Runnable() { public void run() {
long i = 0;
while (i < Constants.EVENT_NUM_OHM) {
Data data = new Data(i, "c" + i);
try {
queue.put(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}).start(); new Thread(new Runnable() {
public void run() {
int k = 0;
while (k < Constants.EVENT_NUM_OHM) {
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
k++;
}
long endTime = System.currentTimeMillis();
System.out.println("ArrayBlockingQueue costTime = " + (endTime - startTime) + "ms");
}
}).start();
}
}
public interface Constants { int EVENT_NUM_OHM = 1000000; int EVENT_NUM_FM = 50000000; int EVENT_NUM_OM = 10000000; }
import java.util.concurrent.Executors; import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType; public class DisruptorSingle4Test { public static void main(String[] args) {
int ringBufferSize = 65536;
final Disruptor<Data> disruptor = new Disruptor<Data>(
new EventFactory<Data>() {
public Data newInstance() {
return new Data();
}
},
ringBufferSize,
Executors.newSingleThreadExecutor(),
ProducerType.SINGLE,
//new BlockingWaitStrategy()
new YieldingWaitStrategy()
); DataConsumer consumer = new DataConsumer();
//消费数据
disruptor.handleEventsWith(consumer);
disruptor.start();
new Thread(new Runnable() { public void run() {
RingBuffer<Data> ringBuffer = disruptor.getRingBuffer();
for (long i = 0; i < Constants.EVENT_NUM_OHM; i++) {
long seq = ringBuffer.next();
Data data = ringBuffer.get(seq);
data.setId(i);
data.setName("c" + i);
ringBuffer.publish(seq);
}
}
}).start();
}
}
import com.lmax.disruptor.EventHandler; public class DataConsumer implements EventHandler<Data> { private long startTime;
private int i; public DataConsumer() {
this.startTime = System.currentTimeMillis();
} public void onEvent(Data data, long seq, boolean bool)
throws Exception {
i++;
if (i == Constants.EVENT_NUM_OHM) {
long endTime = System.currentTimeMillis();
System.out.println("Disruptor costTime = " + (endTime - startTime) + "ms");
}
} }
import java.io.Serializable; public class Data implements Serializable { private static final long serialVersionUID = 2035546038986494352L;
private Long id ;
private String name; public Data() {
}
public Data(Long id, String name) {
super();
this.id = id;
this.name = name;
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
BlockingQueue测试:
1.建立一个工厂Event类,用于创建Event类实例对象
2.需要有一个jian监听事件类,用于处理数据(Event类)
3.实例化Disruptor实例,配置一系列参数,编写DisDisruptor核心组件
4.编写生产者组件,向Disruptor容器中投递数据
pom.xml添加:
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<scope>3.3.2</scope>
</dependency>
public class OrderEvent { private long value; //订单的价格 public long getValue() {
return value;
} public void setValue(long value) {
this.value = value;
}
}
import com.lmax.disruptor.EventFactory; public class OrderEventFactory implements EventFactory<OrderEvent>{ public OrderEvent newInstance() {
return new OrderEvent(); //这个方法就是为了返回空的数据对象(Event)
}
}
public class OrderEventHandler implements EventHandler<OrderEvent>{ public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
Thread.sleep(Integer.MAX_VALUE);
System.err.println("消费者: " + event.getValue());
}
}
import java.nio.ByteBuffer; import com.lmax.disruptor.RingBuffer; public class OrderEventProducer { private RingBuffer<OrderEvent> ringBuffer; public OrderEventProducer(RingBuffer<OrderEvent> ringBuffer) {
this.ringBuffer = ringBuffer;
} public void sendData(ByteBuffer data) {
//1 在生产者发送消息的时候, 首先 需要从我们的ringBuffer里面 获取一个可用的序号
long sequence = ringBuffer.next(); //0
try {
//2 根据这个序号, 找到具体的 "OrderEvent" 元素 注意:此时获取的OrderEvent对象是一个没有被赋值的"空对象"
OrderEvent event = ringBuffer.get(sequence);
//3 进行实际的赋值处理
event.setValue(data.getLong(0));
} finally {
//4 提交发布操作
ringBuffer.publish(sequence);
}
}
}
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType; public class Main {
public static void main(String[] args) {
// 参数准备工作
OrderEventFactory orderEventFactory = new OrderEventFactory();
int ringBufferSize = 4;
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); /**
* 1 eventFactory: 消息(event)工厂对象
* 2 ringBufferSize: 容器的长度
* 3 executor: 线程池(建议使用自定义线程池) RejectedExecutionHandler
* 4 ProducerType: 单生产者 还是 多生产者
* 5 waitStrategy: 等待策略
*/
//1. 实例化disruptor对象
Disruptor<OrderEvent> disruptor = new Disruptor<OrderEvent>(orderEventFactory,
ringBufferSize,
executor,
ProducerType.SINGLE,
new BlockingWaitStrategy()); //2. 添加消费者的监听 (构建disruptor 与 消费者的一个关联关系)
disruptor.handleEventsWith(new OrderEventHandler()); //3. 启动disruptor
disruptor.start(); //4. 获取实际存储数据的容器: RingBuffer
RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer(); OrderEventProducer producer = new OrderEventProducer(ringBuffer); ByteBuffer bb = ByteBuffer.allocate(8); for(long i = 0 ; i < 100; i ++){
bb.putLong(0, i);
producer.sendData(bb);
} disruptor.shutdown();
executor.shutdown(); }
}
public final class BlockingWaitStrategy implements WaitStrategy
{
private final Lock lock = new ReentrantLock();
private final Condition processorNotifyCondition = lock.newCondition(); @Override
public long waitFor(long sequence, Sequence cursorSequence, Sequence dependentSequence, SequenceBarrier barrier)
throws AlertException, InterruptedException
{
long availableSequence;
if ((availableSequence = cursorSequence.get()) < sequence)
{
lock.lock();
try
{
while ((availableSequence = cursorSequence.get()) < sequence)
{
barrier.checkAlert();
processorNotifyCondition.await();
}
}
finally
{
lock.unlock();
}
} while ((availableSequence = dependentSequence.get()) < sequence)
{
barrier.checkAlert();
} return availableSequence;
} @Override
public void signalAllWhenBlocking()
{
lock.lock();
try
{
processorNotifyCondition.signalAll();
}
finally
{
lock.unlock();
}
}
}
public final class SleepingWaitStrategy implements WaitStrategy
{
private static final int DEFAULT_RETRIES = 200; private final int retries; public SleepingWaitStrategy()
{
this(DEFAULT_RETRIES);
} public SleepingWaitStrategy(int retries)
{
this.retries = retries;
} @Override
public long waitFor(final long sequence, Sequence cursor, final Sequence dependentSequence, final SequenceBarrier barrier)
throws AlertException, InterruptedException
{
long availableSequence;
int counter = retries; while ((availableSequence = dependentSequence.get()) < sequence)
{
counter = applyWaitMethod(barrier, counter);
} return availableSequence;
} @Override
public void signalAllWhenBlocking()
{
} private int applyWaitMethod(final SequenceBarrier barrier, int counter)
throws AlertException
{
barrier.checkAlert(); if (counter > 100)
{
--counter;
}
else if (counter > 0)
{
--counter;
Thread.yield();
}
else
{
LockSupport.parkNanos(1L);
} return counter;
}
}
public final class YieldingWaitStrategy implements WaitStrategy
{
private static final int SPIN_TRIES = 100; @Override
public long waitFor(final long sequence, Sequence cursor, final Sequence dependentSequence, final SequenceBarrier barrier)
throws AlertException, InterruptedException
{
long availableSequence;
int counter = SPIN_TRIES; while ((availableSequence = dependentSequence.get()) < sequence)
{
counter = applyWaitMethod(barrier, counter);
} return availableSequence;
} @Override
public void signalAllWhenBlocking()
{
} private int applyWaitMethod(final SequenceBarrier barrier, int counter)
throws AlertException
{
barrier.checkAlert(); if (0 == counter)
{
Thread.yield();
}
else
{
--counter;
} return counter;
}
}
Java 并发框架Disruptor(七)的更多相关文章
- 无锁并发框架Disruptor学习入门
刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...
- Java并发框架AbstractQueuedSynchronizer(AQS)
1.前言 本文介绍一下Java并发框架AQS,这是大神Doug Lea在JDK5的时候设计的一个抽象类,主要用于并发方面,功能强大.在新增的并发包中,很多工具类都能看到这个的影子,比如:CountDo ...
- Java 并发系列之十:java 并发框架(2个)
1. Fork/Join框架 2. Executor框架 3. ThreadPoolExecutor 4. ScheduledThreadPoolExecutor 5. FutureTask 6. t ...
- 深入理解Java并发框架AQS系列(一):线程
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...
- 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...
- 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)
深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...
- 并发框架Disruptor译文
Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一个业务逻辑 ...
- 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock)
一.前言 优秀的源码就在那里 经过了前面两章的铺垫,终于要切入正题了,本章也是整个AQS的核心之一 从本章开始,我们要精读AQS源码,在欣赏它的同时也要学会质疑它.当然本文不会带着大家逐行过源码(会有 ...
- java并发编程系列七:volatile和sinchronized底层实现原理
一.线程安全 1. 怎样让多线程下的类安全起来 无状态.加锁.让类不可变.栈封闭.安全的发布对象 2. 死锁 2.1 死锁概念及解决死锁的原则 一定发生在多个线程争夺多个资源里的情况下,发生的原因是 ...
随机推荐
- java学习笔记(4)运算符
java中的运算符分为以下几种: 算数运算符 +.-.*./.++.--.% 关系运算符 <.<=.>.>=.==.!= 布尔运算符 &&.||.&.| ...
- (10)Go结构体struct
结构体 Go语言中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个 ...
- react的3种组件
推荐阅读:https://www.jianshu.com/p/2726b8654989 1. createClass 已不推荐使用,这里不再多讲.但你仍需要了解它,因为你可能会接触到一些旧项目,或者一 ...
- Spark-Streaming kafka count 案例
Streaming 统计来自 kafka 的数据,这里涉及到的比较,kafka 的数据是使用从 flume 获取到的,这里相当于一个小的案例. 1. 启动 kafka Spark-Streaming ...
- 如何使用Salt Pillar
作者言 Salt的网站上有两篇关于Pillar的文档(一,二),其中一篇内容很少,我觉得写成一篇文章更合适.本文的逻辑结构没有参照官方文档,而是根据我自己对Pillar的理解组织内容,希望能够把这个概 ...
- Nginx系列 | [转]Nginx 上传文件:client_max_body_size 、client_body_buffer_size
原文:http://php-note.com/article/detail/488 client_max_body_size client_max_body_size 默认 1M,表示 客户端请求服务 ...
- Redis系列 | Redis5.0 新特性
- CentOS 7 安装FTP服务器(vsftpd)
FTP是安装各种环境前的预备环节,因为我们要把下载好的安装包上传上去.其次,在一个团队中,FTP服务器为多用户提供了一个文件储存场所,总之是一个非常实用的工具. 1.安装vsftpd # 首先要查看你 ...
- SpringMVC 给请求路径加上统一前缀
最开始想到的是通过硬编码的方式手动在每个路径上加上前缀, 后面发现这种方式太不智能了,万一要修改那还不得改死, Spring既然支持EL表达式, 那能不能通过EL表达式的方式去读取配置文件里面的属性来 ...
- FFMPEG Tips 如何提取码流的基本信息
原文连接: https://zhuanlan.zhihu.com/p/23448271 1. 码流中的哪些信息值得关注 ? [ ] 是否包含:音频.视频 [ ] 码流的封装格式 [ ] 视频的编码格式 ...