beizili

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前言

作为一位开发者,我们经常会接触到“线程”一词,线程意味着并发,但是并发编程是比较困难的。在并发编程中,我们比较关心的就是线程安全问题,解决线程安全问题常用的方法是加锁,可以是乐观锁或者悲观锁,但是我们知道锁技术是很慢的,而且加锁的过程中还很容易出现死锁的现象。Disruptor很好的解决了这些问题。

一、Disruptor究竟是什么

Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题。与Kafka、RabbitMQ用于服务间的消息队列不同,disruptor一般用于线程间消息的传递。基于Disruptor开发的系统单线程能支撑每秒600万订单。

二、Disruptor为什么这么快

1.使用无锁算法来实现并发:

首先,Disruptor根本就不用锁。在需要确保操作是线程安全的地方,Disruptor使用CAS(Compare And Swap/Set)操作。这是一个CPU级别的指令,它的工作方式有点像乐观锁——CPU去更新一个值,但如果想改的值不再是原来的值,操作就失败,因为很明显,有其它操作先改变了这个值。CAS操作比锁消耗资源少的多,因为它们不牵涉操作系统,它们直接在CPU上操作。

2.让消息可以通过被多个消费者并行处理

一般我们在使用队列的时候,队列中的消息只会被一个消费者使用,但是在 Disruptor 中,同一个消息可以被多个消费者同时处理,多个消费者之间是并行的。

3.减少垃圾回收:

Disruptor为了在低延迟的系统中减少进行内存分配,减少垃圾回收所带来的停顿时间,Disruptor使用 RingBuffer 来达成这个目标,在 RingBuffer 中提前创建好对象,后续通过反复利用这些对象来避免垃圾回收,这个实现是线程安全的。

4.缓存行填充

这块比较复杂,大家自行百度,这里就不再赘述。。。。

三、Disruptor实战

maven依赖

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.2</version>
</dependency>
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 *基于Disruptor的Executor,比Java自带的Executor速度快2-3倍.
 * @author syp
 */
public class DisruptorExecutor implements Executor {

    /**
     * 线程名称
     */
    private static final String DEFAULT_EXECUTOR_NAME = "disruptor-executor";
    /**
     * Disruptor的ringBuffer缓存大小,必须是2的幂
     */
    private static final int BUFFER_SIZE = 65536;
    /**
     * 实际执行task的executor
     */
    private final ExecutorService executor;

    private final Disruptor<TaskEvent> disruptor;

    public DisruptorExecutor() {
        this(DEFAULT_EXECUTOR_NAME);
    }

    /**
     * 构造函数.
     *
     * @param name 名称.
     */
    public DisruptorExecutor(String name) {
        this.executor = Executors.newSingleThreadExecutor(r -> new Thread(r, name));
        this.disruptor = new Disruptor<>(TaskEvent::new, BUFFER_SIZE, executor, ProducerType.MULTI,
                new BlockingWaitStrategy());
    }

    /**
     * 启动DisruptorExecutor.
     */
    public void startUp() {
        disruptor.handleExceptionsWith(new LogExceptionHandler());
        disruptor.handleEventsWith((event, sequence, endOfBatch) -> event.getTask().run());
        disruptor.start();
    }

    /**
     * 停止任务调度(阻塞直到所有提交任务完成).
     *
     * @return 结果.
     */
    public boolean awaitAndShutdown() {

        return awaitAndShutdown(Integer.MAX_VALUE, TimeUnit.SECONDS);
    }

    /**
     * 停止任务调度(阻塞直到所有提交任务完成).
     *
     * @param timeout  . 超时时间.
     * @param timeUnit . 时间单位.
     * @return 结果.
     */
    public boolean awaitAndShutdown(long timeout, TimeUnit timeUnit) {
        shutdown();

        try {

            return executor.awaitTermination(timeout, timeUnit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        return false;
    }

    /**
     * 停止任务调度.
     */
    void shutdown() {
        disruptor.shutdown();
        executor.shutdown();
    }

    /**
     * 强制停止任务调度(正在执行的任务将被停止,未执行的任务将被丢弃).
     */
    void halt() {
        executor.shutdownNow();
        disruptor.halt();
    }

    /**
     * 执行任务.
     *
     * @param task . 任务.
     */
    @Override
    public void execute(Runnable task) {
        disruptor.getRingBuffer().publishEvent((event, sequence, buffer) -> event.setTask(task), task);
    }
}

在这里插入图片描述

更多内容请关注微信公众号
在这里插入图片描述

posted on 2020-09-06 23:16  被子里  阅读(12)  评论(0编辑  收藏  举报  来源