最近在泡在网上的日子看到一篇做一个有冒险精神的人!开启慢慢的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. } } }
if (directiveType == GO_TO) { setPausedAtGoToLocked(i); // the actual executor delivery is done below, outside the lock, to eliminate any // deadlock possibility. }
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(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的github上学习,地址为:agera——wiki