Elasticsearch开发AtomicArray使用示例探究

 更新时间:2023年08月07日 14:17:19   作者:codecraft  
这篇文章主要为大家介绍了Elasticsearch AtomicArray使用示例探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下Elasticsearch的AtomicArray

AtomicArray

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/concurrent/AtomicArray.java

public class AtomicArray<E> {
    private final AtomicReferenceArray<E> array;
    private volatile List<E> nonNullList;
    public AtomicArray(int size) {
        array = new AtomicReferenceArray<>(size);
    }
    /**
     * The size of the expected results, including potential null values.
     */
    public int length() {
        return array.length();
    }
    /**
     * Sets the element at position {@code i} to the given value.
     *
     * @param i     the index
     * @param value the new value
     */
    public void set(int i, E value) {
        array.set(i, value);
        if (nonNullList != null) { // read first, lighter, and most times it will be null...
            nonNullList = null;
        }
    }
    public final void setOnce(int i, E value) {
        if (array.compareAndSet(i, null, value) == false) {
            throw new IllegalStateException("index [" + i + "] has already been set");
        }
        if (nonNullList != null) { // read first, lighter, and most times it will be null...
            nonNullList = null;
        }
    }
    /**
     * Gets the current value at position {@code i}.
     *
     * @param i the index
     * @return the current value
     */
    public E get(int i) {
        return array.get(i);
    }
    /**
     * Returns the it as a non null list.
     */
    public List<E> asList() {
        if (nonNullList == null) {
            if (array == null || array.length() == 0) {
                nonNullList = Collections.emptyList();
            } else {
                List<E> list = new ArrayList<>(array.length());
                for (int i = 0; i < array.length(); i++) {
                    E e = array.get(i);
                    if (e != null) {
                        list.add(e);
                    }
                }
                nonNullList = list;
            }
        }
        return nonNullList;
    }
    /**
     * Copies the content of the underlying atomic array to a normal one.
     */
    public E[] toArray(E[] a) {
        if (a.length != array.length()) {
            throw new ElasticsearchGenerationException("AtomicArrays can only be copied to arrays of the same size");
        }
        for (int i = 0; i < array.length(); i++) {
            a[i] = array.get(i);
        }
        return a;
    }
}

AtomicArray封装了AtomicReferenceArray并定义了nonNullList,提供了asList方法转换为ArrayList;

而setOnce方法则使用了AtomicReferenceArray的compareAndSet方法来实现;

另外set及setOnce都会判断nonNullList是否为null,不为null则重新设置为null

GroupedActionListener

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/action/support/GroupedActionListener.java

public final class GroupedActionListener<T> implements ActionListener<T> {
    private final CountDown countDown;
    private final AtomicInteger pos = new AtomicInteger();
    private final AtomicArray<T> results;
    private final ActionListener<Collection<T>> delegate;
    private final Collection<T> defaults;
    private final AtomicReference<Exception> failure = new AtomicReference<>();
    /**
     * Creates a new listener
     * @param delegate the delegate listener
     * @param groupSize the group size
     */
    public GroupedActionListener(ActionListener<Collection<T>> delegate, int groupSize,
                                 Collection<T> defaults) {
        results = new AtomicArray<>(groupSize);
        countDown = new CountDown(groupSize);
        this.delegate = delegate;
        this.defaults = defaults;
    }
    @Override
    public void onResponse(T element) {
        results.setOnce(pos.incrementAndGet() - 1, element);
        if (countDown.countDown()) {
            if (failure.get() != null) {
                delegate.onFailure(failure.get());
            } else {
                List<T> collect = this.results.asList();
                collect.addAll(defaults);
                delegate.onResponse(Collections.unmodifiableList(collect));
            }
        }
    }
    @Override
    public void onFailure(Exception e) {
        if (failure.compareAndSet(null, e) == false) {
            failure.accumulateAndGet(e, (previous, current) -> {
                previous.addSuppressed(current);
                return previous;
            });
        }
        if (countDown.countDown()) {
            delegate.onFailure(failure.get());
        }
    }
}
  • GroupedActionListener的构造器根据groupSize创建了AtomicArray及CountDown
  • onResponse方法会调用AtomicArray的setOnce方法来设置结果,之后判断countDown是否都完成了,完成的话判断是否有failure,有则回调delegate.onFailure,没有failure则调用AtomicArray的asList方法获取list形式的结果,最后回调delegate.onResponse
  • onFailure方法会更新failure,如果compareAndSet失败则使用accumulateAndGet来更新,之后判断countDown是否都完成了,完成的话则回调delegate.onFailure

CountDown

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/concurrent/CountDown.java

public final class CountDown {
    private final AtomicInteger countDown;
    private final int originalCount;
    public CountDown(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count must be greater or equal to 0 but was: " + count);
        }
        this.originalCount = count;
        this.countDown = new AtomicInteger(count);
    }
    /**
     * Decrements the count-down and returns <code>true</code> iff this call
     * reached zero otherwise <code>false</code>
     */
    public boolean countDown() {
        assert originalCount > 0;
        for (;;) {
            final int current = countDown.get();
            assert current >= 0;
            if (current == 0) {
                return false;
            }
            if (countDown.compareAndSet(current, current - 1)) {
                return current == 1;
            }
        }
    }
    /**
     * Fast forwards the count-down to zero and returns <code>true</code> iff
     * the count down reached zero with this fast forward call otherwise
     * <code>false</code>
     */
    public boolean fastForward() {
        assert originalCount > 0;
        assert countDown.get() >= 0;
        return countDown.getAndSet(0) > 0;
    }
    /**
     * Returns <code>true</code> iff the count-down has reached zero. Otherwise <code>false</code>
     */
    public boolean isCountedDown() {
        assert countDown.get() >= 0;
        return countDown.get() == 0;
    }
}

CountDown是一个简易线程安全非阻塞版的CountDownLatch,它提供了countDown方法使用compareAndSet来递减值,同时返回countDown是否完成(countDown.get() == 0);

另外还提供了isCountedDown来查询countDown是否完成;还有fastForward方法用于将countDown直接设置为0

小结

  • AtomicArray封装了AtomicReferenceArray并定义了nonNullList,提供了asList方法转换为ArrayList;而setOnce方法则使用了AtomicReferenceArray的compareAndSet方法来实现;
  • 另外set及setOnce都会判断nonNullList是否为null,不为null则重新设置为null
  • GroupedActionListener的构造器根据groupSize创建了AtomicArray及CountDown;
  • onResponse方法会调用AtomicArray的setOnce方法来设置结果,之后判断countDown是否都完成了,完成的话判断是否有failure,有则回调delegate.onFailure,没有failure则调用AtomicArray的asList方法获取list形式的结果,最后回调delegate.onResponse;
  • onFailure方法会更新failure,如果compareAndSet失败则使用accumulateAndGet来更新,之后判断countDown是否都完成了,完成的话则回调delegate.onFailure
  • CountDown是一个简易线程安全非阻塞版的CountDownLatch,它提供了countDown方法使用compareAndSet来递减值,同时返回countDown是否完成(countDown.get() == 0);
  • 另外还提供了isCountedDown来查询countDown是否完成;还有fastForward方法用于将countDown直接设置为0

doc

以上就是Elasticsearch AtomicArray使用示例探究的详细内容,更多关于Elasticsearch AtomicArray的资料请关注脚本之家其它相关文章!

相关文章

  • JAVA 多态 由浅及深介绍

    JAVA 多态 由浅及深介绍

    JAVA 多态 由浅及深介绍,什么是多态?多态的详细解释,多态的好处,多态的实际运用等
    2013-03-03
  • springboot实现excel表格导出几种常见方法

    springboot实现excel表格导出几种常见方法

    在日常的开发中避免不了操作Excel,下面这篇文章主要给大家介绍了关于springboot实现excel表格导出的几种常见方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • Java图片裁剪和生成缩略图的实例方法

    Java图片裁剪和生成缩略图的实例方法

    这篇文章主要介绍了Java图片裁剪和生成缩略图的实例方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-01-01
  • 浅谈java继承中是否创建父类对象

    浅谈java继承中是否创建父类对象

    下面小编就为大家带来一篇浅谈java继承中是否创建父类对象。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • SpringAMQP消息队列(SpringBoot集成RabbitMQ方式)

    SpringAMQP消息队列(SpringBoot集成RabbitMQ方式)

    这篇文章主要介绍了SpringAMQP消息队列(SpringBoot集成RabbitMQ方式),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Spring核心思想之浅谈IoC容器与依赖倒置(DI)

    Spring核心思想之浅谈IoC容器与依赖倒置(DI)

    文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyBatis则通过动态代理实现了接口方法到数据库操作的映射,文章详细解释了Spring和MyBatis的工作原理,并通过示例代码展示了它们的结合使用方式
    2025-01-01
  • Java多线程中不同条件下编写生产消费者模型方法介绍

    Java多线程中不同条件下编写生产消费者模型方法介绍

    这篇文章主要介绍了Java多线程中不同条件下编写生产消费者模型方法介绍,介绍了生产消费者模型,然后分享了相关代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • mybatis映射文件mapper.xml的具体写法

    mybatis映射文件mapper.xml的具体写法

    在开发过程中,需要开发人员配置mapper映射文件,本文主要介绍了mybatis映射文件mapper.xml的具体写法,感兴趣的可以了解一下
    2021-09-09
  • Java实现选择排序算法的实例教程

    Java实现选择排序算法的实例教程

    这篇文章主要介绍了Java实现选择排序算法的实例教程,选择排序的时间复杂度为О(n&sup2;),需要的朋友可以参考下
    2016-05-05
  • Java代码注释规范详解

    Java代码注释规范详解

    代码附有注释对程序开发者来说非常重要,随着技术的发展,在项目开发过程中,必须要求程序员写好代码注释,这样有利于代码后续的编写和使用。下面给大家分享java代码注释的规范,需要的朋友参考下
    2016-02-02

最新评论