Startup设计与实现

644 阅读3分钟

设计

任务的分类

  • 主线程,阻塞
  • 主线程,非阻塞(不常用)
  • 子线程,阻塞(很少见)
  • 子线程,非阻塞

这里阻塞的含义是指在application的onCreate方法里完成。
任务的分类有点多,有必要精简吗

前序任务

不管什么类型的任务,都可以有后序任务
只有一个例外,就是主线程,非阻塞的任务,不能有阻塞的后序任务。

任务的优先级

不管是主线程还是子线程,优先级高的先执行

多进程

任意任务可以在任意进程执行

实现

定义接口 Task

public interface Task extends Runnable {

    /**
     * @return 前序任务
     */
    List<Class<? extends Task>> dependencies();

    /**
     * @return 是否主线程
     */
    boolean isMainThread();

    /**
     * @return 是否阻塞
     */
    boolean isBlocking();

    /**
     * @return 优先级,数值越大,优先级越高
     */
    int priority();

    /**
     * @return 是否主进程
     */
    boolean isMainProcess();

    /**
     * @return 进程列表
     */
    Set<String> processes();

}

RealTask

public class RealTask extends AtomicInteger implements Task, Comparable<RealTask> {

    static final int START = 0;
    static final int RUNNING = 1;
    static final int COMPLETE = 2;

    final Context mContext;

    /**
     * task运行状态
     */
    AtomicInteger state;

    /**
     * 原始任务
     */
    final Task source;

    /**
     * 后序任务
     */
    final List<RealTask> nextList;

    public RealTask(Context context, Task task) {
        mContext = context;
        this.source = task;
        nextList = new ArrayList<>();
        state = new AtomicInteger();
    }

    @Override
    public List<Class<? extends Task>> dependencies() {
        return source.dependencies();
    }

    @Override
    public boolean isMainThread() {
        return source.isMainThread();
    }

    @Override
    public boolean isBlocking() {
        return source.isBlocking();
    }

    @Override
    public int priority() {
        return source.priority();
    }

    @Override
    public boolean isMainProcess() {
        return source.isMainProcess();
    }

    @Override
    public Set<String> processes() {
        Set<String> processes = source.processes();
        if (processes == null) {
            processes = new HashSet<>();
        }
        return processes;
    }

    @Override
    public int compareTo(RealTask o) {
        if (isMainThread()) {
            if (o.isMainThread()) {
                return o.priority() - priority();
            } else {
                return 1;
            }
        } else {
            if (o.isMainThread()) {
                return -1;
            } else {
                return o.priority() - priority();
            }
        }
    }

    @Override
    public void run() {
        state.set(RUNNING);
        long start = System.currentTimeMillis();
        boolean shouldRun = shouldRun();
        if (shouldRun) {
            source.run();
        }
        long end = System.currentTimeMillis();
        state.set(COMPLETE);

        System.out.println("task=" + source.getClass().getSimpleName());
        System.out.println("start= " + start);
        System.out.println("end= " + end + " cost= " + (end - start));
        if (!shouldRun) {
            System.out.println("task not run");
        }

        /*
         * 执行后续任务
         * 1. 任务在主线程,并且是非阻塞的,需要运行
         * 2. 任务在子线程,需要运行
         */
        if (!nextList.isEmpty()) {
            for (RealTask next : nextList) {
                if (next.decrementAndGet() == 0) {
                    if (next.isMainThread()) {
                        if (!next.isBlocking()) {
                            ThreadUtils.runOnUiThread(next);
                        }
                    } else {
                        ThreadUtils.runOnIoThread(next);
                    }
                }
            }
        }
    }

    /**
     * @return 是否需要运行
     */
    private boolean shouldRun() {
        String processName = ProcessUtils.getCurrentProcessName(mContext);
        if (ProcessUtils.isMainProcess(mContext, processName)) {
            if (isMainProcess()) {
                return true;
            } else {
                return processes().contains(processName);
            }
        } else {
            return processes().contains(processName);
        }
    }

    /**
     * 更新前序任务
     */
    public void increment() {
        incrementAndGet();
    }

    /**
     * 添加后序任务
     */
    public void addNextTask(RealTask task) {
        nextList.add(task);
    }

    /**
     * @return 当前任务能否开始,即前序任务有没有完成
     */
    public boolean canStart() {
        return get() == 0;
    }

    /**
     * @return 当前任务是否完成
     */
    public boolean isDone() {
        return state.get() == COMPLETE;
    }
}

AtomicInteger

初始值为0
每有一个前序任务加1
每完成一个前序任务减1

Comparable

@Override
public int compareTo(RealTask o) {
    if (isMainThread()) {
        if (o.isMainThread()) {
            return o.priority() - priority();
        } else {
            return 1;
        }
    } else {
        if (o.isMainThread()) {
            return -1;
        } else {
            return o.priority() - priority();
        }
    }
}
  • 线程相同的情况下,优先级高的先运行
  • 线程不同的情况下,子线程先运行
  • 这里的运行,不一定真的运行,要根据前序任务

多进程逻辑

private boolean shouldRun() {
    String processName = ProcessUtils.getCurrentProcessName(mContext);
    if (ProcessUtils.isMainProcess(mContext, processName)) {
        if (isMainProcess()) {
            return true;
        } else {
            return processes().contains(processName);
        }
    } else {
        return processes().contains(processName);
    }
}
  1. 主进程时,先判断isMainProcess,如果不是主进程,走3
  2. 其他进程时,走3
  3. 判断进程列表是否包含该进程,有可能包含主进程

执行逻辑

@Override
public void run() {
    ...

    if (!nextList.isEmpty()) {
        for (RealTask next : nextList) {
            if (next.decrementAndGet() == 0) {
                if (next.isMainThread()) {
                    if (!next.isBlocking()) {
                        ThreadUtils.runOnUiThread(next);
                    }
                } else {
                    ThreadUtils.runOnIoThread(next);
                }
            }
        }
    }
}
  • 后序任务在主线程,并且是非阻塞的,直接运行
  • 后序任务在子线程,直接运行

Startup

public final class Startup {

    private static volatile Startup sInstance;

    final Context mContext;

    final List<Class<? extends Task>> taskList;
    final Map<Class<?>, Task> taskMap;

    final List<RealTask> realTaskList;
    final Map<Class<?>, RealTask> realTaskMap;

    /**
     * 启动队列,包括
     * 1. 主线程,阻塞的任务
     * 2. 子线程,阻塞的任务
     */
    final Queue<RealTask> queue;

    /**
     * 子线程,非阻塞
     */
    final Queue<RealTask> ioQueue;

    /**
     * 主线程,非阻塞
     */
    final Queue<RealTask> mainQueue;

    Startup(Context context) {
        mContext = context.getApplicationContext();
        taskList = new ArrayList<>();
        taskMap = new HashMap<>();
        realTaskList = new ArrayList<>();
        realTaskMap = new HashMap<>();
        queue = new LinkedList<>();
        ioQueue = new LinkedList<>();
        mainQueue = new LinkedList<>();
    }

    public static Startup getInstance(Context context) {
        if (sInstance == null) {
            synchronized (Startup.class) {
                if (sInstance == null) {
                    sInstance = new Startup(context);
                }
            }
        }
        return sInstance;
    }

    public Startup addTask(Class<? extends Task> component) {
        taskList.add(component);
        return this;
    }

    private void prepare(List<Class<? extends Task>> list) {
        for (Class<? extends Task> component : list) {
            prepare0(component);
        }
    }

    private void prepare0(Class<? extends Task> component) {
        prepare0(component, new HashSet<>());
    }

    private void prepare0(Class<? extends Task> component, Set<Class<?>> initializing) {
        if (initializing.contains(component)) {
            String message = String.format("循环依赖 %s.", component.getName());
            throw new StartupException(message);
        }

        try {
            if (!taskMap.containsKey(component)) {
                initializing.add(component);
                Object instance = component.getDeclaredConstructor().newInstance();
                Task initializer = (Task) instance;
                List<Class<? extends Task>> sublist = initializer.dependencies();

                if (sublist != null && !sublist.isEmpty()) {
                    for (int i = 0; i < sublist.size(); i++) {
                        if (!taskMap.containsKey(sublist.get(i))) {
                            prepare0(sublist.get(i), initializing);
                        }
                    }
                }
                initializing.remove(component);
                taskMap.put(component, initializer);
            }
        } catch (Throwable t) {
            throw new StartupException(t);
        }
    }

    private void check() {
        for (RealTask task : realTaskList) {
            if (task.isMainThread() && !task.isBlocking()) {
                check0(task);
            }
        }
    }

    private void check0(RealTask task) {
        List<RealTask> list = task.nextList;
        if (list != null && !list.isEmpty()) {
            for (RealTask next : list) {
                if (next.isBlocking()) {
                    String message = String.format("主线程,非阻塞任务不能依赖阻塞任务 %s.", task.getClass().getSimpleName());
                    throw new StartupException(message);
                } else {
                    check0(next);
                }
            }
        }
    }

    public void start() {
        // 创建任务对象,检测循环依赖
        prepare(taskList);

        // 创建包装任务
        for (Map.Entry<Class<?>, Task> entry : taskMap.entrySet()) {
            Class<?> clazz = entry.getKey();
            Task initializer = entry.getValue();
            RealTask task = new RealTask(mContext, initializer);
            realTaskList.add(task);
            realTaskMap.put(clazz, task);
        }

        // 添加后序任务,统计前序任务数量
        for (RealTask task : realTaskList) {
            List<Class<? extends Task>> sublist = task.dependencies();
            if (sublist != null && !sublist.isEmpty()) {
                for (Class<? extends Task> clazz : sublist) {
                    RealTask subTask = realTaskMap.get(clazz);
                    if (subTask != null) {
                        subTask.addNextTask(task);
                        task.increment();
                    }
                }
            }
        }

        // 检测
        check();

        // 所有任务排序
        Collections.sort(realTaskList, RealTask::compareTo);

        // 后序任务排序
        for (RealTask task : realTaskList) {
            List<RealTask> list = task.nextList;
            if (list != null && !list.isEmpty()) {
                Collections.sort(list, RealTask::compareTo);
            }
        }

        // 分组任务
        for (RealTask task : realTaskList) {
            if (task.isMainThread()) {
                if (task.isBlocking()) {
                    queue.offer(task);
                } else {
                    mainQueue.offer(task);
                }
            } else {
                if (task.isBlocking()) {
                    queue.offer(task);
                } else {
                    ioQueue.offer(task);
                }
            }
        }

        // 先执行子线程的非阻塞任务
        while (!ioQueue.isEmpty()) {
            RealTask task = ioQueue.poll();
            if (task != null) {
                if (task.canStart()) {
                    ThreadUtils.runOnIoThread(task);
                }
            }
        }

        // 执行阻塞任务
        while (!queue.isEmpty()) {
            RealTask task = queue.poll();
            if (task != null) {
                if (task.isDone()) {
                    continue;
                }
                if (!task.canStart()) {
                    queue.offer(task);
                    continue;
                }
                if (task.isMainThread()) {
                    if (task.isBlocking()) {
                        task.run();
                    }
                } else {
                    ThreadUtils.runOnIoThread(task);
                }
            }
        }

        // 执行主线程的非阻塞任务
        while (!mainQueue.isEmpty()) {
            RealTask task = mainQueue.poll();
            if (task != null) {
                ThreadUtils.runOnUiThread(task);
            }
        }
    }

}
  • 单例模式
  • 递归的方式检测循环依赖
  • 建立任务的前后依赖关系
  • 递归的方式检测任务合理性
  • 排序,后序任务也要排序
  • 所有任务进行分组
  • 执行任务

总结

本文主要描述了Application启动任务的优化。
部分代码参考了官方Startup库。