本文主要研究一下Elasticsearch的Releasables

Releasable

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/lease/Releasable.java

public interface Releasable extends Closeable {

    @Override
    void close();

}
  • Releasable继承了java.io.Closeable接口

Releasables

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/lease/Releasables.java

public enum Releasables {
    ;

    private static void close(Iterable<? extends Releasable> releasables, boolean ignoreException) {
        try {
            // this does the right thing with respect to add suppressed and not wrapping errors etc.
            IOUtils.close(releasables);
        } catch (IOException e) {
            if (ignoreException == false) {
                throw new UncheckedIOException(e);
            }
        }
    }

    /** Release the provided {@link Releasable}s. */
    public static void close(Iterable<? extends Releasable> releasables) {
        close(releasables, false);
    }

    /** Release the provided {@link Releasable}s. */
    public static void close(Releasable... releasables) {
        close(Arrays.asList(releasables));
    }

    /** Release the provided {@link Releasable}s, ignoring exceptions. */
    public static void closeWhileHandlingException(Iterable<Releasable> releasables) {
        close(releasables, true);
    }

    /** Release the provided {@link Releasable}s, ignoring exceptions. */
    public static void closeWhileHandlingException(Releasable... releasables) {
        closeWhileHandlingException(Arrays.asList(releasables));
    }

    /** Release the provided {@link Releasable}s, ignoring exceptions if <code>success</code> is {@code false}. */
    public static void close(boolean success, Iterable<Releasable> releasables) {
        if (success) {
            close(releasables);
        } else {
            closeWhileHandlingException(releasables);
        }
    }

    /** Release the provided {@link Releasable}s, ignoring exceptions if <code>success</code> is {@code false}. */
    public static void close(boolean success, Releasable... releasables) {
        close(success, Arrays.asList(releasables));
    }

    /** Wrap several releasables into a single one. This is typically useful for use with try-with-resources: for example let's assume
     *  that you store in a list several resources that you would like to see released after execution of the try block:
     *
     *  <pre>
     *  List&lt;Releasable&gt; resources = ...;
     *  try (Releasable releasable = Releasables.wrap(resources)) {
     *      // do something
     *  }
     *  // the resources will be released when reaching here
     *  </pre>
     */
    public static Releasable wrap(final Iterable<Releasable> releasables) {
        return () -> close(releasables);
    }

    /** @see #wrap(Iterable) */
    public static Releasable wrap(final Releasable... releasables) {
        return () -> close(releasables);
    }

    /**
     * Equivalent to {@link #wrap(Releasable...)} but can be called multiple times without double releasing.
     */
    public static Releasable releaseOnce(final Releasable... releasables) {
        final AtomicBoolean released = new AtomicBoolean(false);
        return () -> {
            if (released.compareAndSet(false, true)) {
                close(releasables);
            }
        };
    }
}
  • Releasables提供close、closeWhileHandlingException、wrap、releaseOnce静态方法用于更方便地使用Releasable

实例

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/index/translog/Translog.java

public class Translog extends AbstractIndexShardComponent implements IndexShardComponent, Closeable {

    //......

    public static void writeOperations(StreamOutput outStream, List<Operation> toWrite) throws IOException {
        final ReleasableBytesStreamOutput out = new ReleasableBytesStreamOutput(BigArrays.NON_RECYCLING_INSTANCE);
        try {
            outStream.writeInt(toWrite.size());
            final BufferedChecksumStreamOutput checksumStreamOutput = new BufferedChecksumStreamOutput(out);
            for (Operation op : toWrite) {
                out.reset();
                final long start = out.position();
                out.skip(Integer.BYTES);
                writeOperationNoSize(checksumStreamOutput, op);
                long end = out.position();
                int operationSize = (int) (out.position() - Integer.BYTES - start);
                out.seek(start);
                out.writeInt(operationSize);
                out.seek(end);
                ReleasablePagedBytesReference bytes = out.bytes();
                bytes.writeTo(outStream);
            }
        } finally {
            Releasables.close(out);
        }

    }

    //......
}
  • writeOperations在finally中使用Releasables.close关闭了ReleasableBytesStreamOutput

小结

Releasables提供close、closeWhileHandlingException、wrap、releaseOnce静态方法用于更方便地使用Releasable

doc


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...