AsyncHttpClient ListenableFuture源碼流程解讀
序
本文主要研究一下AsyncHttpClient的ListenableFuture
ListenableFuture
org/asynchttpclient/ListenableFuture.java
public interface ListenableFuture<V> extends Future<V> {
/**
* Terminate and if there is no exception, mark this Future as done and release the internal lock.
*/
void done();
/**
* Abort the current processing, and propagate the {@link Throwable} to the {@link AsyncHandler} or {@link Future}
*
* @param t the exception
*/
void abort(Throwable t);
/**
* Touch the current instance to prevent external service to times out.
*/
void touch();
/**
* Adds a listener and executor to the ListenableFuture.
* The listener will be {@linkplain java.util.concurrent.Executor#execute(Runnable) passed
* to the executor} for execution when the {@code Future}'s computation is
* {@linkplain Future#isDone() complete}.
* <br>
* Executor can be <code>null</code>, in that case executor will be executed
* in the thread where completion happens.
* <br>
* There is no guaranteed ordering of execution of listeners, they may get
* called in the order they were added and they may get called out of order,
* but any listener added through this method is guaranteed to be called once
* the computation is complete.
*
* @param listener the listener to run when the computation is complete.
* @param exec the executor to run the listener in.
* @return this Future
*/
ListenableFuture<V> addListener(Runnable listener, Executor exec);
CompletableFuture<V> toCompletableFuture();
//......
}ListenableFuture繼承了java.util.concurrent.Future,它定義了done、abort、touch、addListener、toCompletableFuture方法
CompletedFailure
org/asynchttpclient/ListenableFuture.java
class CompletedFailure<T> implements ListenableFuture<T> {
private final ExecutionException e;
public CompletedFailure(Throwable t) {
e = new ExecutionException(t);
}
public CompletedFailure(String message, Throwable t) {
e = new ExecutionException(message, t);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return true;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return true;
}
@Override
public T get() throws ExecutionException {
throw e;
}
@Override
public T get(long timeout, TimeUnit unit) throws ExecutionException {
throw e;
}
@Override
public void done() {
}
@Override
public void abort(Throwable t) {
}
@Override
public void touch() {
}
@Override
public ListenableFuture<T> addListener(Runnable listener, Executor exec) {
if (exec != null) {
exec.execute(listener);
} else {
listener.run();
}
return this;
}
@Override
public CompletableFuture<T> toCompletableFuture() {
CompletableFuture<T> future = new CompletableFuture<>();
future.completeExceptionally(e);
return future;
}
}CompletedFailure實現(xiàn)了ListenableFuture接口,其cancel方法返回true、isDone返回true
NettyResponseFuture
org/asynchttpclient/netty/NettyResponseFuture.java
public final class NettyResponseFuture<V> implements ListenableFuture<V> {
private static final Logger LOGGER = LoggerFactory.getLogger(NettyResponseFuture.class);
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> REDIRECT_COUNT_UPDATER = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "redirectCount");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> CURRENT_RETRY_UPDATER = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "currentRetry");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IS_DONE_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "isDone");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IS_CANCELLED_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "isCancelled");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IN_AUTH_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "inAuth");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IN_PROXY_AUTH_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "inProxyAuth");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> CONTENT_PROCESSED_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "contentProcessed");
@SuppressWarnings("rawtypes")
private static final AtomicIntegerFieldUpdater<NettyResponseFuture> ON_THROWABLE_CALLED_FIELD = AtomicIntegerFieldUpdater
.newUpdater(NettyResponseFuture.class, "onThrowableCalled");
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater<NettyResponseFuture, TimeoutsHolder> TIMEOUTS_HOLDER_FIELD = AtomicReferenceFieldUpdater
.newUpdater(NettyResponseFuture.class, TimeoutsHolder.class, "timeoutsHolder");
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater<NettyResponseFuture, Object> PARTITION_KEY_LOCK_FIELD = AtomicReferenceFieldUpdater
.newUpdater(NettyResponseFuture.class, Object.class, "partitionKeyLock");
private final long start = unpreciseMillisTime();
private final ChannelPoolPartitioning connectionPoolPartitioning;
private final ConnectionSemaphore connectionSemaphore;
private final ProxyServer proxyServer;
private final int maxRetry;
private final CompletableFuture<V> future = new CompletableFuture<>();
//......
@Override
public V get() throws InterruptedException, ExecutionException {
return future.get();
}
@Override
public V get(long l, TimeUnit tu) throws InterruptedException, TimeoutException, ExecutionException {
return future.get(l, tu);
}
}NettyResponseFuture實現(xiàn)了ListenableFuture接口
done
public final void done() {
if (terminateAndExit())
return;
try {
loadContent();
} catch (ExecutionException ignored) {
} catch (RuntimeException t) {
future.completeExceptionally(t);
} catch (Throwable t) {
future.completeExceptionally(t);
throw t;
}
}
private boolean terminateAndExit() {
releasePartitionKeyLock();
cancelTimeouts();
this.channel = null;
this.reuseChannel = false;
return IS_DONE_FIELD.getAndSet(this, 1) != 0 || isCancelled != 0;
}
private void loadContent() throws ExecutionException {
if (future.isDone()) {
try {
future.get();
} catch (InterruptedException e) {
throw new RuntimeException("unreachable", e);
}
}
// No more retry
CURRENT_RETRY_UPDATER.set(this, maxRetry);
if (CONTENT_PROCESSED_FIELD.getAndSet(this, 1) == 0) {
try {
future.complete(asyncHandler.onCompleted());
} catch (Throwable ex) {
if (ON_THROWABLE_CALLED_FIELD.getAndSet(this, 1) == 0) {
try {
try {
asyncHandler.onThrowable(ex);
} catch (Throwable t) {
LOGGER.debug("asyncHandler.onThrowable", t);
}
} finally {
cancelTimeouts();
}
}
future.completeExceptionally(ex);
}
}
future.getNow(null);
}done方法對于terminateAndExit返回true的直接返回,否則執(zhí)行l(wèi)oadContent,它對于future.isDone()的執(zhí)行future.get(),然后執(zhí)行future.complete(asyncHandler.onCompleted())回調(diào)
abort
public final void abort(final Throwable t) {
if (terminateAndExit())
return;
future.completeExceptionally(t);
if (ON_THROWABLE_CALLED_FIELD.compareAndSet(this, 0, 1)) {
try {
asyncHandler.onThrowable(t);
} catch (Throwable te) {
LOGGER.debug("asyncHandler.onThrowable", te);
}
}
}abort方法也是對于terminateAndExit返回true的直接返回,否則執(zhí)行future.completeExceptionally(t),然后觸發(fā)asyncHandler.onThrowable(t)回調(diào)
touch
public void touch() {
touch = unpreciseMillisTime();
}touch方法用當(dāng)前時間戳更新touch屬性
addListener
public ListenableFuture<V> addListener(Runnable listener, Executor exec) {
if (exec == null) {
exec = Runnable::run;
}
future.whenCompleteAsync((r, v) -> listener.run(), exec);
return this;
}addListener方法會執(zhí)行future.whenCompleteAsync((r, v) -> listener.run(), exec)
toCompletableFuture
public CompletableFuture<V> toCompletableFuture() {
return future;
}toCompletableFuture方法直接返回future
newNettyResponseFuture
org/asynchttpclient/netty/request/NettyRequestSender.java
private <T> NettyResponseFuture<T> newNettyResponseFuture(Request request,
AsyncHandler<T> asyncHandler,
NettyRequest nettyRequest,
ProxyServer proxyServer) {
NettyResponseFuture<T> future = new NettyResponseFuture<>(
request,
asyncHandler,
nettyRequest,
config.getMaxRequestRetry(),
request.getChannelPoolPartitioning(),
connectionSemaphore,
proxyServer);
String expectHeader = request.getHeaders().get(EXPECT);
if (HttpHeaderValues.CONTINUE.contentEqualsIgnoreCase(expectHeader))
future.setDontWriteBodyBecauseExpectContinue(true);
return future;
}
private <T> ListenableFuture<T> sendRequestWithCertainForceConnect(Request request,
AsyncHandler<T> asyncHandler,
NettyResponseFuture<T> future,
ProxyServer proxyServer,
boolean performConnectRequest) {
NettyResponseFuture<T> newFuture = newNettyRequestAndResponseFuture(request, asyncHandler, future, proxyServer,
performConnectRequest);
Channel channel = getOpenChannel(future, request, proxyServer, asyncHandler);
return Channels.isChannelActive(channel)
? sendRequestWithOpenChannel(newFuture, asyncHandler, channel)
: sendRequestWithNewChannel(request, proxyServer, newFuture, asyncHandler);
}NettyRequestSender的newNettyResponseFuture創(chuàng)建的是NettyResponseFuture;sendRequestWithCertainForceConnect則將NettyResponseFuture傳遞給sendRequestWithOpenChannel或者sendRequestWithNewChannel來發(fā)送請求
小結(jié)
AsyncHttpClient的ListenableFuture繼承了java.util.concurrent.Future,它定義了done、abort、touch、addListener、toCompletableFuture方法;它有兩個實現(xiàn)類,分別是CompletedFailure及NettyResponseFuture;NettyRequestSender的sendRequest方法將NettyResponseFuture傳遞給sendRequestWithOpenChannel或者sendRequestWithNewChannel來發(fā)送請求。
以上就是聊聊AsyncHttpClient的ListenableFuture的詳細(xì)內(nèi)容,更多關(guān)于AsyncHttpClient的ListenableFuture的資料請關(guān)注腳本之家其它相關(guān)文章!
以上就是AsyncHttpClient ListenableFuture源碼流程解讀的詳細(xì)內(nèi)容,更多關(guān)于AsyncHttpClient ListenableFuture的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot自動配置實現(xiàn)的詳細(xì)步驟
這篇文章主要為大家介紹了SpringBoot自動配置實現(xiàn)詳細(xì)的過程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
JAVA實現(xiàn)數(shù)字大寫金額轉(zhuǎn)換的方法
這篇文章主要介紹了JAVA實現(xiàn)數(shù)字大寫金額轉(zhuǎn)換的方法,涉及java針對字符串與數(shù)組的遍歷與轉(zhuǎn)換相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07
Java中定時任務(wù)的全方位場景實現(xiàn)思路分析
在開發(fā)過程中,根據(jù)需求和業(yè)務(wù)的不同經(jīng)常會有很多場景需要用到不同特性的定時任務(wù),本文將針對這些場景,提供不同的一個實現(xiàn)思路,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧2023-12-12
Java實現(xiàn)正則匹配 “1234567” 這個字符串出現(xiàn)四次或四次以上
文章介紹了如何在Java中使用正則表達式匹配一個字符串四次或四次以上的出現(xiàn),首先創(chuàng)建正則表達式,然后使用Pattern和Matcher類進行匹配和計數(shù),通過示例代碼展示了如何實現(xiàn)這一功能,并解釋了匹配的整體次數(shù)和精確出現(xiàn)次數(shù)的邏輯,感興趣的朋友一起看看吧2025-02-02
詳解Java中的reactive stream協(xié)議
Stream大家應(yīng)該都很熟悉了,java8中為所有的集合類都引入了Stream的概念。優(yōu)雅的鏈?zhǔn)讲僮?,流式處理邏輯,相信用過的人都會愛不釋手。本文將詳細(xì)介紹Java中的reactive stream協(xié)議。2021-06-06
SpringBoot配置文件中數(shù)據(jù)庫密碼加密兩種方案(推薦)
SpringBoot項目經(jīng)常將連接數(shù)據(jù)庫的密碼明文放在配置文件里,安全性就比較低一些,尤其在一些企業(yè)對安全性要求很高,因此我們就考慮如何對密碼進行加密,文中給大家介紹加密的兩種方式,感興趣的朋友一起看看吧2019-10-10

