五、并发框架disruptor-高级进阶(一)

1、介绍

  上一篇只是介绍了disruptor的核心概念,并举例了单消费单生产,本文将介绍各种消费类型

2、消费操作

2.1、事前准备

2.1.1、创建Event类

@Data
public class Trade {

    private String id;
    private String name;
    private double price;
    private AtomicInteger count = new AtomicInteger(0);
}

2.1.2、创建提交任务的方式

public class TradePublisher implements Runnable {

    private Disruptor disruptor;
    private CountDownLatch latch;
    private static int PUBLISH_COUNT = 1;

    public TradePublisher(CountDownLatch latch, Disruptor disruptor) {
        this.disruptor = disruptor;
        this.latch = latch;
    }

    /**
     * When an object implementing interface Runnable is used
     * to create a thread, starting the thread causes the object's
     * run method to be called in that separately executing
     * thread.
     * 

* The general contract of the method run is that it may * take any action whatsoever. * * @see Thread#run() */ @Override public void run() { TradeEventTranslator eventTranslator = new TradeEventTranslator(); for(int i=0; i{ private Random random = new Random(); @Override public void translateTo(Trade event, long sequence) { this.generateTrade(event); } private void generateTrade(Trade event) { event.setPrice(random.nextDouble() *9999); } } }

2.1.3、创建5个消费者

消费者1

public class Handler1 implements EventHandler , WorkHandler {

    // EventHandler
    @Override
    public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
       this.onEvent(trade);
    }

    // WorkHandler
    @Override
    public void onEvent(Trade trade) throws Exception {
        System.err.println("handler 1 : SET NAME");
        trade.setName("H1");
        Thread.sleep(1000);
    }
}

消费者2

public class Handler2 implements EventHandler {
    @Override
    public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 2 : SET ID");
        trade.setId(UUID.randomUUID().toString());
        Thread.sleep(2000);
    }
}

消费者3

public class Handler3 implements EventHandler {
    @Override
    public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {

        System.err.println("handler 3 : NAME:"+ trade.getName()
                +",ID:"+trade.getId() + ",INSTANCE:"+trade.toString());
    }
}

消费者4

public class Handler4 implements EventHandler {
    @Override
    public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 4 : SET PRICE");
        trade.setPrice(17.0);
    }
}

消费者5

public class Handler5 implements EventHandler {
    @Override
    public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 5 : GET PRICE:" + trade.getPrice());
        trade.setPrice(trade.getPrice() + 3.0);
    }
}

2.2、串行操作

package com.example.disruptor.height.chain;

import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) throws InterruptedException {


        // 构建一个线程池用于提交任务
        ExecutorService executorService1 = Executors.newFixedThreadPool(4);
        ExecutorService executorService2 = Executors.newFixedThreadPool(5);

        // 参数准备工作
        int ringBufferSize = 1024 * 1024;
        // 线程
        /**
         * 1 eventFactory: 消息(event)工厂对象
         * 2 ringBufferSize: 容器的长度
         * 3 executorService:线程池(建议使用自定义线程池)RejectedExecutionHandler
         * 4 ProducerType:单生产者还是多生产者
         * 5 waitStrategy:等待策略
         */
        // 1.实例化disruptor对象
        Disruptor disruptor = new Disruptor(new EventFactory() {
            @Override
            public Trade newInstance() {
                return new Trade();
            }
        },
                ringBufferSize,
                executorService2,
                ProducerType.SINGLE,
                new BusySpinWaitStrategy()
        );
        // 2.把消费者设置到Disruptor中handleEventsWith

        // 2.1.串行操作
        disruptor
                .handleEventsWith(new Handler1())
                .handleEventsWith(new Handler2())
                .handleEventsWith(new Handler3());
        
        // 3. 启动disruptor
        RingBuffer ringBuffer = disruptor.start();

        CountDownLatch latch = new CountDownLatch(1);

        Long start = System.currentTimeMillis();

        executorService1.submit(new TradePublisher(latch, disruptor));
        // 进行向下执行
        latch.await();

        disruptor.shutdown();
        executorService1.shutdown();
        executorService2.shutdown();

        Long end = System.currentTimeMillis();
        System.out.println("总耗时" + (end - start));

    }
}

执行结果
在这里插入图片描述
因为是串行,执行完1,之后是2,最后3打印会有所有的值

2.3、并行操作

2.3.1、第一种并行方式

disruptor.handleEventsWith(new Handler1());
disruptor.handleEventsWith(new Handler2());
disruptor.handleEventsWith(new Handler3());

执行结果
在这里插入图片描述

2.3.2、第二种并行方式

disruptor.handleEventsWith(new Handler1(),new Handler2(),new Handler3());

执行结果在这里插入图片描述
由上面两种方式可以看出,并行操作,在执行完3之后并没有1、2执行的结果,导致id和名称都是null

2.4、菱形操作

        /**
         *  h1 ->
         *         h3
         *  h2 ->
        */

2.4.1、第一种方式

disruptor.handleEventsWith(new Handler1(), new Handler2()).
         handleEventsWith(new Handler3());

执行结果
在这里插入图片描述
2.4.2、第二种方式

 EventHandlerGroup eventHandlerGroup = disruptor.handleEventsWith(new Handler1(), new Handler2());
        eventHandlerGroup.then(new Handler3());

执行结果在这里插入图片描述
实际执行控制台会将1、2直接打印,最后执行完会打印3

2.5、六边形操作

  /*
                 1.1. h1 -> h2
          start                      2.h3
                 1.2. h4 -> h5

        */
        Handler1 h1 = new Handler1();
        Handler2 h2 = new Handler2();
        Handler3 h3 = new Handler3();
        Handler4 h4 = new Handler4();
        Handler5 h5 = new Handler5();
        disruptor.handleEventsWith(h1, h4);
        disruptor.after(h1).handleEventsWith(h2);
        disruptor.after(h4).handleEventsWith(h5);
        disruptor.after(h2, h5).handleEventsWith(h3);

执行结果
在这里插入图片描述
由上可以看出,不管是串行还是并行等,disruptor支持各种模式的,完全是可以应用到不同的业务场景中,这样节约了串行导致的消耗时间

你可能感兴趣的:(Java)