Elasticsearch開發(fā)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方法來實現(xiàn);
另外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的構造器根據(jù)groupSize創(chuàng)建了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方法來實現(xiàn);
- 另外set及setOnce都會判斷nonNullList是否為null,不為null則重新設置為null
- GroupedActionListener的構造器根據(jù)groupSize創(chuàng)建了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的資料請關注腳本之家其它相關文章!
相關文章
springboot實現(xiàn)excel表格導出幾種常見方法
在日常的開發(fā)中避免不了操作Excel,下面這篇文章主要給大家介紹了關于springboot實現(xiàn)excel表格導出的幾種常見方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-11-11
SpringAMQP消息隊列(SpringBoot集成RabbitMQ方式)
這篇文章主要介紹了SpringAMQP消息隊列(SpringBoot集成RabbitMQ方式),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04

