1、
2、
常规异步,代码不够优雅。比如说,这里有很多service.submit(new Runnable()),有8个任务,执行了8次。那如果有100个任务,需要submit()100次吗?这样会导致,一是代码不够优雅,别人接手的时候也不是很舒服。
第二点是,比如这个initWeex()方法,需要在application的onCreate()方法中直接执行完成,需要怎么做?我们的处理方式是使用countdownlaunch.await()和countdownlatch.countDown(),但是比较繁琐。那如果有多个任务,是不是就需要多个countdownlatch()或者传入countdownlatch的参数需要一个更大的值呢?这是一个问题,还有一个问题是,多个任务之间可能存在依赖关系,这种依赖关系针对普通的异步任务很不好处理。
比如有一个initJPush()这个操作,initJPush()的时候可能需要一个deviceId,担任如果getDeviceId()和initJPush()可能是分开的,这种分开肯定是有问题的。比如说initJPush()之前就需要拿到deviceId(),然后在initJPush()的时候把deviceId带上。如果分开进行操作,可能会拿不到。
可以直接把getDeviceId()拿到initJPush()之前,这样可以解决问题,但是在实际操作中,有很多实际的操作,可能有时候不能直接将别人的操作拿到我们的操作之前,比如从110行开始,这里已经有10个任务,不可能从其它地方拿到一个任务,直接放进去,这个很多情况下是不可以的。这又是另一个问题,任务之间有依赖关系。常规的异步方法对这种情况非常不好处理。另一方面是不方便统计。首先这个代码并不优雅,即便是自己定义runnable,添加统计的代码,但是这种方案仍然不方便统计。首先代码不优雅,就是需要抛弃掉的。常规的异步代码对大型项目其实是不足够的,或者说不足以满足要求,需要对异步方案进行升级。
3、
4、
5、
6、
最前面有一个head task,尾部其实还有一个tail task和ilde task。head task就是所有task执行之前做的事情,这里可以做一个所有task都需要的代码的一个注入,或者说简单打一下log之类的。tail task可以在所有任务结束之后,打印log或者上报数据都可以。ide task类似于ilde handler,是在程序空闲的时候才会执行的。
如果没有执行异步任务的话,所有的任务都会执行在主线程,为了别的线程可以分担主线程的责任,引入了并发,就是多个线程同时来执行。
启动器会在主线程执行一些任务,也会在子线程执行一些代码。这就是并发。
7、
TaskDispatcher()是启动器的入口
init()是使用之前需要对它进行初始化,只需要传入context就可以了
每次使用启动器之前需要调用createInstance()这个方法,其实是屏蔽了它的默认构造方法
有一个公开的API是addTask(),是往启动器中添加代码,添加一个task。接下来的一系列操作是对后续的一个辅助。
addTask()调用完后会调用start()方法。其中调用了TaskSortUtil.getSortResult()方法
TaskSortUtil也是一个很重要的类。它会生成任务的有向无环图的拓扑排序。
拓扑排序以后会生成一个集合,
之后,TaskDispatcher的start()方法会执行一些代码
比如这里执行的是一些异步任务。
这里执行了主线程的任务。
public class TaskDispatcher {
private long mStartTime;
private static final int WAITTIME = 10000;
private static Context sContext;
private static boolean sIsMainProcess;
private List<Future> mFutures = new ArrayList<>();
private static volatile boolean sHasInit;
private List<Task> mAllTasks = new ArrayList<>();
private List<Class<? extends Task>> mClsAllTasks = new ArrayList<>();
private volatile List<Task> mMainThreadTasks = new ArrayList<>();
private CountDownLatch mCountDownLatch;
private AtomicInteger mNeedWaitCount = new AtomicInteger();//保存需要Wait的Task的数量
private List<Task> mNeedWaitTasks = new ArrayList<>();//调用了await的时候还没结束的且需要等待的Task
private volatile List<Class<? extends Task>> mFinishedTasks = new ArrayList<>(100);//已经结束了的Task
private HashMap<Class<? extends Task>, ArrayList<Task>> mDependedHashMap = new HashMap<>();
private AtomicInteger mAnalyseCount = new AtomicInteger();//启动器分析的次数,统计下分析的耗时;
private TaskDispatcher() {
}
public static void init(Context context) {
if (context != null) {
sContext = context;
sHasInit = true;
sIsMainProcess = Utils.isMainProcess(sContext);
}
}
/**
* 注意:每次获取的都是新对象
*
* @return
*/
public static TaskDispatcher createInstance() {
if (!sHasInit) {
throw new RuntimeException("must call TaskDispatcher.init first");
}
return new TaskDispatcher();
}
public TaskDispatcher addTask(Task task) {
if (task != null) {
collectDepends(task);
mAllTasks.add(task);
mClsAllTasks.add(task.getClass());
// 非主线程且需要wait的,主线程不需要CountDownLatch也是同步的
if (ifNeedWait(task)) {
mNeedWaitTasks.add(task);
mNeedWaitCount.getAndIncrement();
}
}
return this;
}
private void collectDepends(Task task) {
if (task.dependsOn() != null && task.dependsOn().size() > 0) {
for (Class<? extends Task> cls : task.dependsOn()) {
if (mDependedHashMap.get(cls) == null) {
mDependedHashMap.put(cls, new ArrayList<Task>());
}
mDependedHashMap.get(cls).add(task);
if (mFinishedTasks.contains(cls)) {
task.satisfy();
}
}
}
}
private boolean ifNeedWait(Task task) {
return !task.runOnMainThread() && task.needWait();
}
@UiThread
public void start() {
mStartTime = System.currentTimeMillis();
if (Looper.getMainLooper() != Looper.myLooper()) {
throw new RuntimeException("must be called from UiThread");
}
if (mAllTasks.size() > 0) {
mAnalyseCount.getAndIncrement();
printDependedMsg();
mAllTasks = TaskSortUtil.getSortResult(mAllTasks, mClsAllTasks);
mCountDownLatch = new CountDownLatch(mNeedWaitCount.get());
sendAndExecuteAsyncTasks();
DispatcherLog.i("task analyse cost " + (System.currentTimeMillis() - mStartTime) + " begin main ");
executeTaskMain();
}
DispatcherLog.i("task analyse cost startTime cost " + (System.currentTimeMillis() - mStartTime));
}
public void cancel() {
for (Future future : mFutures) {
future.cancel(true);
}
}
private void executeTaskMain() {
mStartTime = System.currentTimeMillis();
for (Task task : mMainThreadTasks) {
long time = System.currentTimeMillis();
new DispatchRunnable(task,this).run();
DispatcherLog.i("real main " + task.getClass().getSimpleName() + " cost " +
(System.currentTimeMillis() - time));
}
DispatcherLog.i("maintask cost " + (System.currentTimeMillis() - mStartTime));
}
private void sendAndExecuteAsyncTasks() {
for (Task task : mAllTasks) {
if (task.onlyInMainProcess() && !sIsMainProcess) {
markTaskDone(task);
} else {
sendTaskReal(task);
}
task.setSend(true);
}
}
/**
* 查看被依赖的信息
*/
private void printDependedMsg() {
DispatcherLog.i("needWait size : " + (mNeedWaitCount.get()));
if (false) {
for (Class<? extends Task> cls : mDependedHashMap.keySet()) {
DispatcherLog.i("cls " + cls.getSimpleName() + " " + mDependedHashMap.get(cls).size());
for (Task task : mDependedHashMap.get(cls)) {
DispatcherLog.i("cls " + task.getClass().getSimpleName());
}
}
}
}
/**
* 通知Children一个前置任务已完成
*
* @param launchTask
*/
public void satisfyChildren(Task launchTask) {
ArrayList<Task> arrayList = mDependedHashMap.get(launchTask.getClass());
if (arrayList != null && arrayList.size() > 0) {
for (Task task : arrayList) {
task.satisfy();
}
}
}
public void markTaskDone(Task task) {
if (ifNeedWait(task)) {
mFinishedTasks.add(task.getClass());
mNeedWaitTasks.remove(task);
mCountDownLatch.countDown();
mNeedWaitCount.getAndDecrement();
}
}
private void sendTaskReal(final Task task) {
if (task.runOnMainThread()) {
mMainThreadTasks.add(task);
if (task.needCall()) {
task.setTaskCallBack(new TaskCallBack() {
@Override
public void call() {
TaskStat.markTaskDone();
task.setFinished(true);
satisfyChildren(task);
markTaskDone(task);
DispatcherLog.i(task.getClass().getSimpleName() + " finish");
Log.i("testLog", "call");
}
});
}
} else {
// 直接发,是否执行取决于具体线程池
Future future = task.runOn().submit(new DispatchRunnable(task,this));
mFutures.add(future);
}
}
public void executeTask(Task task) {
if (ifNeedWait(task)) {
mNeedWaitCount.getAndIncrement();
}
task.runOn().execute(new DispatchRunnable(task,this));
}
@UiThread
public void await() {
try {
if (DispatcherLog.isDebug()) {
DispatcherLog.i("still has " + mNeedWaitCount.get());
for (Task task : mNeedWaitTasks) {
DispatcherLog.i("needWait: " + task.getClass().getSimpleName());
}
}
if (mNeedWaitCount.get() > 0) {
mCountDownLatch.await(WAITTIME, TimeUnit.MILLISECONDS);
}
} catch (InterruptedException e) {
}
}
public static Context getContext() {
return sContext;
}
public static boolean isMainProcess() {
return sIsMainProcess;
}
}