异步初始化最优解--启动器一

241 篇文章 5 订阅

 

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;
    }
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值