最近在泡在网上的日子看到一篇做一个有冒险精神的人!开启慢慢的agera之旅,然后就抱着学习的心态去了解啦一下。
结合人家写的文章与源码,自己大概的了解啦agera的内部框架,在这里我就补充一点点自己所学的东西。
agera中异步调用的机制:
<span style="font-size:18px;"> @NonNull
@Override
public RepositoryCompiler goTo(@NonNull final Executor executor) {
checkExpect(FLOW);
checkGoLazyUnused();
addGoTo(executor, directives);
return this;
}</span>
goto方法中传入Executor类型的参数,可以用过
<span style="font-size:18px;"><span style="white-space:pre"> </span>Executors.newCachedThreadPool();
Executors.newFixedThreadPool(int count);
Executors.newSingleThreadExecutor();
Executors.newScheduledThreadPool(int count)</span>
来获取。
然后看addGoTo方法:
static void addGoTo(@NonNull final Executor executor,
@NonNull final List<Object> directives) {
directives.add(GO_TO);
directives.add(executor);
}
directices就是一个数组,里面维护了数据流的操作以及操作的标示符
就下来就要去看directices里的数据是怎么进行操作的:
private void runFlowFrom(final int index, final boolean asynchronously) {
final Object[] directives = this.directives;
final int length = directives.length;
int i = index;
while (0 <= i && i < length) {
int directiveType = (Integer) directives[i];
if (asynchronously || directiveType == GO_TO || directiveType == GO_LAZY) {
// Check cancellation before running the next directive. This needs to be done while locked.
// For goTo and goLazy, because they need to change the states and suspend the flow, they
// need the lock and are therefore treated specially here.
synchronized (this) {
if (checkCancellationLocked()) {
break;
}
if (directiveType == GO_TO) {
setPausedAtGoToLocked(i);
// the actual executor delivery is done below, outside the lock, to eliminate any
// deadlock possibility.
} else if (directiveType == GO_LAZY) {
setLazyAndEndFlowLocked(i);
return;
}
}
}
// A table-switch on a handful of options is a good compromise in code size and runtime
// performance comparing to a full-fledged double-dispatch pattern with subclasses.
switch (directiveType) {
case GET_FROM:
i = runGetFrom(directives, i);
break;
case MERGE_IN:
i = runMergeIn(directives, i);
break;
case TRANSFORM:
i = runTransform(directives, i);
break;
case CHECK:
i = runCheck(directives, i);
break;
case GO_TO:
i = runGoTo(directives, i);
break;
case SEND_TO:
i = runSendTo(directives, i);
break;
case BIND:
i = runBindWith(directives, i);
break;
case FILTER_SUCCESS:
i = runFilterSuccess(directives, i);
break;
case END:
i = runEnd(directives, i);
break;
// Missing GO_LAZY but it has already been dealt with in the synchronized block above.
}
}
}
里面是通过directiveType来进行判断的
if (directiveType == GO_TO) {
setPausedAtGoToLocked(i);
// the actual executor delivery is done below, outside the lock, to eliminate any
// deadlock possibility.
}
当directiveType为GO_TO标记时就调用setPauseAtToLocked();
private void setPausedAtGoToLocked(final int resumeIndex) {
lastDirectiveIndex = resumeIndex;
runState = PAUSED_AT_GO_TO;
}
这里首先是记录一下当前位置,这个位置的作用在后面会说到,然后就是把当前运行的状态进行改变
然后程序运行到switch语句块的逻辑,就会调用runGoTo方法:
private int runGoTo(@NonNull final Object[] directives, final int index) {
Executor executor = (Executor) directives[index + 1];
executor.execute(this);
return -1;
}
这里就会拿到线程池来执行Runnable中的run方法,this所指的类型中实现啦Runnable接口
/** Called from the executor of a goTo instruction to continue processing. */
@Override
public void run() {
Thread myThread = currentThread();
int index;
synchronized (this) {
index = lastDirectiveIndex;
checkState(runState == PAUSED_AT_GO_TO || runState == CANCEL_REQUESTED,
"Illegal call of Runnable.run()");
lastDirectiveIndex = -1;
if (checkCancellationLocked()) {
return;
}
runState = RUNNING;
// allow thread interruption (set this when still holding the lock)
currentThread = myThread;
}
// leave the synchronization lock to run the rest of the flow
runFlowFrom(continueFromGoTo(directives, index), true);
// consume any unconsumed interrupted flag
Thread.interrupted();
// disallow interrupting the current thread, but chances are the next directive has started
// asynchronously, so check currentThread is still this thread. This also works if a goTo
// directive is given a synchronous executor, in which case the next part of the flow will
// have been completed by now and currentThread will have been reset by that invocation of
// runFlowFrom().
synchronized (this) {
if (currentThread == myThread) {
currentThread = null;
}
}
}
在这段代码中可以看到,执行啦runFlowFrom方法
runFlowFrom(continueFromGoTo(directives, index), true);
continueFromGoTo方法中的index,就是我们上面那个setPauseATGoToLocked方法中的lastDirectiveIndex,所以在这个runFlowFrom中操作的是GoTo之后的流操作,比如:
<span style="white-space:pre"> </span>.getFrom(supplier)
.goTo(Executors.newSingleThreadExecutor())
.transform(function)
getFrom中的supplier在Observable中的线程中执行,而transform中的function在Executors.newSingleThreadExecutore中执行。
这点可以从runFlowFrom的注解可以看出
// leave the synchronization lock to run the rest of the flow
离开同步锁去执行余下的部分
// disallow interrupting the current thread, but chances are the next directive has started // asynchronously, so check currentThread is still this thread. This also works if a goTo // directive is given a synchronous executor, in which case the next part of the flow will // have been completed by now and currentThread will have been reset by that invocation of // runFlowFrom().这一段注解告诉我们,如果我们想让GoTo之后的流操作运行在别的线程池里,我们就需要在调用一次GoTo就可以啦!
综上:我们要是想在agera中进行异步操作,我们就需要把要异步的操作流放在goTo方法之后,这样后面的操作流就会运行在goTo所指定的线程池中!
对于进一步的学习可以去agera的github上学习,地址为:agera——wiki