原文地址:http://www.cnblogs.com/qiaoyihang/p/6479994.html  

  disruptor适用于大规模低延迟的并发场景。可用于读写操作分离、数据缓存,速度匹配(因为其实现了生产者-消费者模型)、或者是基于内存的事件流处理机制的场景。

  disruptor的主要设计思想是无锁的高并发,特别适用于对时间高度敏感的多线程应用。如果app对时间不敏感完全可以不用disruptor 而只用array blocking queue,在设计上采用内存屏障的机制和CAS操作实现此思想。主流的并发程序 
  都离不开锁对资源的管控,或者尽量避开锁的使用。 
  其主要的实现原理总结有如下三点,当然还有很多地方设计得很巧妙,需要细细阅读源码和官方文档。虽然这个 过程对我来说很尴尬,但痛并快乐者,有朝闻道、夕可死也的感觉。 
  1.采用消费者-生产者模型进行读写的分离。 
  2.用循环缓存(实际是一个循环队列)实现了数据的暂存和读写速度的匹配。 
  3.用内存屏障加序列号的方式实现了无锁的并发机制。

在插一下cas机制

CAS,又称Compare-and-Swap,代表一种原子操作

一, 为每一个Node在Set的时候分配一个cas值,(本质是版本号,返回的Node和存储Node的cas值一样,每次要更新这个Node时要检查cas的值是否与取出来时一致)

二, 只有在Update一个key的value时才会造成多线程冲突,只是Set/Get是不会的,单线程也不会并发问题。

三, 如何维护每个线程/进程的cas的值:

增加步进的概念:cas每次自增每个线程都不一样,这样的话,每个线程有一个确定的变量,如果是由其它线程修改的一定与本线程的cas不一样

1, 每个线程/进程有一个初始化的index,如果有10个进程就是编号为0 ~9

2, 每次cas值增加都是按进程数来加,step[0] += 10,这样能保证每个进程的cas都不会一样

3,缺点是需要额外的初始化

cas 使用场景:

线程T1对key1、线程T2对Key1并发Get更新了Value值后想Set回去,可能会出现后一个操作覆盖前一个操作值,而且这个值是涉及到事务性的。正确是应该是T1 Set完后,T2才能取,串行化操作。

CAS就是解决这个问题,如果发现cas值不一样了,就会Set失败,需要重取再设置,假定某时刻T1 的cas值为20,T2 的cas值为21。如果没有步进时,T1处理后cas值为21,T2再处理就认为没有改变过。

disruptor的主要编程部件 
   1.Disruptor:用于控制整个消费者-生产者模型的处理器 
   2.RingBuffer:用于存放数据 
   3.EventHandler:一个用于处理事件的接口(可以当做生产者,也可以当做消费者)。 
   4.EventFactory:事件工厂类。 
   5.WaitStrategy:用于实现事件处理等待RingBuffer游标策略的接口。 
   6.SequeueBarrier:队列屏障,用于处理访问RingBuffer的序列。 
   7.用于运行disruptor的线程或者线程池。

 -disruptor编程主要的编程流程 
   1.定义事件 
   2.定义事件工厂 
   3.定义事件处理类 
   4.定义事件处理的线程或者线程池 
   5.指定等待策略 
   6.通过disruptor处理器组装生产者和消费者 
   7.发布事件 
   8.关闭disruptor业务逻辑处理器

disruptor实现无锁高并发,主要采用的消费者-生产者模型。所以编程的实践场景如下 
   1.一个生产者—一个消费者的场景 
   2.一个生产者—多个消费者的场景 
   3.多个生产者—一个消费者的场景 
   4.多个生产者—多个消费者的场景

记录一下自己写的demo,模拟三个消费者消费一个生产者的数据,最后等待所有线程都执行完毕才进行下一步操作:

//首先定义一个事件
public class MyEvent {
private String name;
private CountDownLatch countDownLatch; public CountDownLatch getCountDownLatch() {
return countDownLatch;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} public void setMyEvent(MyEvent myEvent){
name = myEvent.name;
countDownLatch = myEvent.countDownLatch;
} }
//生产数据的工厂
public class MyEventFactory implements EventFactory<MyEvent> { @Override
public MyEvent newInstance() {
// TODO Auto-generated method stub
return new MyEvent();
} }
//数据构造
public class MyEventProduce implements Runnable {
private final int SIZE = 3;
private CountDownLatch countDownLatch;
private Disruptor<MyEvent> disruptor; public MyEventProduce() {
countDownLatch = new CountDownLatch(SIZE);
} public MyEventProduce setDisruptor(Disruptor<MyEvent> disruptor) {
this.disruptor = disruptor;
return this;
} public CountDownLatch getCountDownLatch() {
return countDownLatch;
} @Override
public void run() {
for (int i = 1; i <= SIZE; i++) {
MyEvent event = new MyEvent();
event.setName("name--" + i);
event.setCountDownLatch(countDownLatch);
disruptor.publishEvent(new MyEventTranslator(event));
}
} }
public class MyEventTranslator implements EventTranslator<MyEvent> {
private MyEvent myEvent; public MyEventTranslator(MyEvent myEvent) {
this.myEvent = myEvent;
} @Override
public void translateTo(MyEvent event, long sequence) {
event.setMyEvent(myEvent);
} }
//第一个消费者
public class Handler1 implements EventHandler<MyEvent>, WorkHandler<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(Handler1.class); @Override
public void onEvent(MyEvent event) throws Exception {
log.debug(event.getName() + "====Handler1 。。。。");
// throw new RuntimeException("测试异常");
} @Override
public void onEvent(MyEvent event, long sequence, boolean endOfBatch)
throws Exception {
System.out.println("not go");
onEvent(event);
} }
//第二个消费者
public class Handler11 implements EventHandler<MyEvent>, WorkHandler<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(Handler11.class); @Override
public void onEvent(MyEvent event) throws Exception {
log.debug(event.getName() + "====Handler11 。。。。。");
} @Override
public void onEvent(MyEvent event, long sequence, boolean endOfBatch)
throws Exception {
onEvent(event);
} }
//第三个消费者
public class Handler2 implements EventHandler<MyEvent>, WorkHandler<MyEvent> {
private static final Logger log = LoggerFactory.getLogger(Handler2.class); @Override
public void onEvent(MyEvent event) throws Exception {
log.debug(event.getName() + "====Handler2........");
event.getCountDownLatch().countDown();
} @Override
public void onEvent(MyEvent event, long sequence, boolean endOfBatch)
throws Exception {
onEvent(event);
} }
//异常处理事件类
public class MyHandlerException implements ExceptionHandler { /*
* (non-Javadoc)
*
* @see
* com.lmax.disruptor.ExceptionHandler#handleEventException(java.lang.Throwable
* , long, java.lang.Object)
*/
@Override
public void handleEventException(Throwable ex, long sequence, Object event) {
// TODO Auto-generated method stub
System.out.println("MyHandlerException handleEventException...");
} /*
* (non-Javadoc)
*
* @see
* com.lmax.disruptor.ExceptionHandler#handleOnStartException(java.lang.
* Throwable)
*/
@Override
public void handleOnStartException(Throwable ex) {
System.out.println("MyHandlerException handleOnStartException...");
} /*
* (non-Javadoc)
*
* @see
* com.lmax.disruptor.ExceptionHandler#handleOnShutdownException(java.lang
* .Throwable)
*/
@Override
public void handleOnShutdownException(Throwable ex) {
System.out.println("MyHandlerException handleOnShutdownException...");
} }
//单元测试类
public class TestDisruptor {
private static final Logger log = LoggerFactory
.getLogger(TestDisruptor.class); @Test
public void myTest() throws Exception {
Disruptor<MyEvent> disruptor = new Disruptor<>(new MyEventFactory(),
1024, Exector.newInstance().getExecutorService(),
ProducerType.SINGLE, new YieldingWaitStrategy()); disruptor.handleExceptionsWith(new MyHandlerException());
disruptor.handleEventsWithWorkerPool(new Handler1())
.thenHandleEventsWithWorkerPool(new Handler11())
.thenHandleEventsWithWorkerPool(new Handler2()); disruptor.start(); MyEventProduce ep = new MyEventProduce().setDisruptor(disruptor);
CountDownLatch countDownLatch = ep.getCountDownLatch();
Exector.newInstance().getExecutorService().submit(ep);
countDownLatch.await();
disruptor.shutdown(); log.debug("运行完毕");
} public void testJDBC() throws Exception { Connection connection = DriverManager.getConnection("", "", ""); }
}

文章借鉴:http://blog.csdn.net/jeffsmish/article/details/53572043

推荐文章:http://blog.163.com/zongyuan1987@126/blog/static/131623156201271021955717/

disruptor 高并发编程 简介demo的更多相关文章

  1. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  2. Java高并发编程基础三大利器之CountDownLatch

    引言 上一篇文章我们介绍了AQS的信号量Semaphore<Java高并发编程基础三大利器之Semaphore>,接下来应该轮到CountDownLatch了. 什么是CountDownL ...

  3. Java 面试知识点解析(二)——高并发编程篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  4. java高并发编程(一)

    读马士兵java高并发编程,引用他的代码,做个记录. 一.分析下面程序输出: /** * 分析一下这个程序的输出 * @author mashibing */ package yxxy.c_005; ...

  5. java线程高并发编程

    java线程具体解释及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了.看看百度百科对他的评价,一点也不为过: 假设IT的历史 ...

  6. Java 多线程高并发编程 笔记(一)

    本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...

  7. 多线程高并发编程(3) -- ReentrantLock源码分析AQS

    背景: AbstractQueuedSynchronizer(AQS) public abstract class AbstractQueuedSynchronizer extends Abstrac ...

  8. 关于Java高并发编程你需要知道的“升段攻略”

    关于Java高并发编程你需要知道的"升段攻略" 基础 Thread对象调用start()方法包含的步骤 通过jvm告诉操作系统创建Thread 操作系统开辟内存并使用Windows ...

  9. java并发编程笔记(一)——并发编程简介

    java并发编程笔记(一)--简介 线程不安全的类示例 public class CountExample1 { // 请求总数 public static int clientTotal = 500 ...

随机推荐

  1. linux学习笔记5--命令rmdir和rm

    昨天学习了创建目录的命令mkdir ,接下来学习一下linux中删除文件和目录的命令: rm命令. rm是一个危险的命令,使用的时候要特别当心,尤其对于新手,否则整个系统就会毁在这个命令(比如在/(根 ...

  2. Retrofit--官网2.1.0

    Retrofit--官网2.1.0 android Retrofit 介绍 API 描述 请求方法 URL 处理 请求体 表单的 ENCODED 和 MULTIPART HEADER 处理 同步 VS ...

  3. 基于jQuery的让非HTML5浏览器支持placeholder属性的代码(转)

    效果图:http://code.google.com/p/jquery-placeholder-js/ 演示代码:http://demo.jb51.net/js/2011/jqueryplacehol ...

  4. zookeeper安装与集群搭建

    此处以centos系统下zookeeper安装为例,详细步骤可参考官网文档:zookeeper教程 一.单节点部署 1.下载zookeeper wget http://mirrors.hust.edu ...

  5. Memcached集群:Magent缓存代理使用

    小结: 先启动memcached 然后启动magent memcached -d -p 11211 -u memcached -m 64 -c 5120 memcached -d -p 11212 - ...

  6. C++ 抽象类二(抽象类的基本语法)

    //抽象类的基本语法 #include<iostream> using namespace std; /* 有关多继承的说明 被实际开发经验抛弃的多继承 工程开发中真正意义上的多继承是几乎 ...

  7. 初识NuGet及快速安装使用

    为什么要使用NuGet 简单的说NuGet可以是我们的工作更方便,当我们的项目里要引用到的一些库时候,比如JQuery.Newtonsoft.Json. log4net等,我们需要从网上下载这些库,然 ...

  8. centos6.5安装apache2

    参考 http://my.oschina.net/u/593517/blog/340289 http://blog.csdn.net/hkmaike/article/details/9732177

  9. android去权限反编译,签名,zipalign优化

    反编译:上工具ApkTool 下载自行搜索google  apktool github cd apktool目录 java -jar apktool_2.0.1.jar d xx.apk 生成xx目录 ...

  10. Linux各文件颜色的含义

    Linux系统中文件有多种颜色,不同颜色文件代表不同类型的文件,具体如下: 蓝色:目录 绿色:可执行文件 红色:压缩文件 浅蓝色:链接文件 白色:普通文件 黄色:设备文件