如何设计一个基于DAG的启动任务管理框架

202 阅读2分钟
enum class LaunchPeriod(val value: Int) {
    Init(0),
    BeforeAttachBase(1),
    AfterAttachBase(2),
    BeforeOnCreate(3),
    AfterOnCreate(4)
}

interface ILaunchTask : Runnable {
    val id: String
    fun runInMainThread(): Boolean
    fun getEarliestPeriod(): LaunchPeriod?  // 任务可以开始执行的最早时间
    fun getLatestPeriod(): LaunchPeriod     // 任务最晚必须在这个时间内被执行
    fun dependOn(): MutableList<String>     // 该启动任务依赖的其他启动任务
}

class LaunchTask(private val option: Option, private val toRun: () -> Unit) : ILaunchTask {
    data class Option(
        val id: String,
        val inMainThread: Boolean,
        val earliestPeriod: LaunchPeriod?,
        val latestPeriod: LaunchPeriod,
        val dependOn: MutableList<String>? = null
    )

    override val id = option.id
    override fun runInMainThread(): Boolean = option.inMainThread
    override fun getEarliestPeriod(): LaunchPeriod? = option.earliestPeriod
    override fun getLatestPeriod(): LaunchPeriod = option.latestPeriod
    override fun dependOn(): MutableList<String> = option.dependOn ?: mutableListOf()
    override fun run() = toRun()
}

class TaskExtraInfo {
    var priority = -1   // Task优先级
    var startTime = 0L  // 开始时间
    var endTime = 0L    // 结束时间
    val children = mutableListOf<ILaunchTask>()     // 依赖该Task的Task
    val parent = mutableListOf<ILaunchTask>()       // 该Task依赖的Task
    val dependent = mutableListOf<ILaunchTask>()    // 依赖该Task的Task,动态变化
}

class RocketApplication : Application() {
    private lateinit var initLoader: IAppInitLoader

    private fun initAppLoader() {
        initLoader = MainProcessInitLoader(this)
    }

    override fun attachBaseContext(base: Context) {
        initAppLoader()
        initLoader.attachBaseContext(base)
    }

    @SuppressLint("MissingSuperCall")
    override fun onCreate() {
        initLoader.onCreate()
    }
}


interface IAppInitLoader {
    fun attachBaseContext(base: Context)
    fun onCreate()
}


class MainProcessInitLoader(private val application: RocketApplication) : IAppInitLoader {

    val launchDispatcher = LaunchDispatcher(application) {
        // 通过with添加Task
    }

    override fun attachBaseContext(base: Context) {
        launchDispatcher.launch()                // 启动线程,内部循环添加线程池
        launchDispatcher.appAttachBase()        // takeMainThread
    }

    override fun onCreate() {
        launchDispatcher.appOnCreate()        // takeMainThread
    }
}


class LaunchDispatcher(application: RocketApplication, block: LaunchTaskContainer.() -> Unit) :
    Runnable {
    private val taskManager = LaunchTaskManager(application)
    private val threadNumber = AtomicInteger(1)
    private var dispatchThread: Thread? = null
    private var launchTime = System.currentTimeMillis()
    private val threadFactory = ThreadFactory {
        Thread("Launcher")
    }
    private val executor: ExecutorService =
        ThreadPoolExecutor(
            8, 8,
            0L, TimeUnit.MILLISECONDS, LinkedBlockingQueue(), threadFactory
        )

    init {
        taskManager.block()
        taskManager.classify()
    }

    fun launch() {
        val dispatchThread = Thread(this)
        dispatchThread.name = "LaunchDispatcher"
        dispatchThread.start()
        this.dispatchThread = dispatchThread
    }

    fun appAttachBase() {
        takeMainThread()
    }

    fun appOnCreate() {
        takeMainThread()
    }

    private fun takeMainThread() {
        while (true) {
            var task: ILaunchTask?
            task = taskManager.takeUiReadyTaskIfExist()
            if (task == null) {
                synchronized(this) {
                    task = taskManager.takeNonUiTaskIfExist(10)
                }
            }
            val localTask = task ?: continue
            localTask.run()
            if (localTask is MainThreadCompleteTask) {
                logMainThreadCompleteTask(localTask.id)
                break
            }
        }
    }

    override fun run() {
        while (true) {
            var task: ILaunchTask?
            synchronized(this) {
                task = taskManager.takeNonUiTaskIfExist()
            }
            val localTask = task ?: break
            executor.execute {
                localTask.run()
            }
        }
    }
}

interface LaunchTaskContainer {
    fun with(task: ILaunchTask)
}

class LaunchTaskManager(application: RocketApplication) : LaunchTaskContainer {

    private val tmpTaskList: MutableList<ILaunchTask> = arrayListOf()

    private val allCustomTask: MutableList<ILaunchTask> = arrayListOf()

    private val appAttachBaseStart = AppOnAttachBaseStart()
    private val superAttachBase = AppSuperAttachBase(application)
    private val attachBaseComplete = AppAttachBaseCompleteTask()

    private val appOnCreateStart = AppOnCreateStart()
    private val superOnCreate = AppSuperOnCreate(application)
    private val onCreateComplete = AppOnCreateCompleteTask()

    private val unDispatchTask = mutableListOf<ILaunchTask>()

    private val readyQueue = PriorityBlockingQueue<PriorityLaunchTask>()
    private val uiReadyQueue = PriorityBlockingQueue<PriorityLaunchTask>()

    private val taskExtra = ConcurrentHashMap<ILaunchTask, TaskExtraInfo>()

    override fun with(task: ILaunchTask) {
        tmpTaskList.add(task)
    }

    fun classify() {
        initData()
        initDepend()
        initReadyQueue()
    }

    private fun initData() {
        allCustomTask.clear()
        allCustomTask.addAll(tmpTaskList)
        tmpTaskList.clear()

        allCustomTask.forEach { task ->
            unDispatchTask.add(task)
        }

        unDispatchTask.add(superAttachBase)
        unDispatchTask.add(superOnCreate)
        unDispatchTask.add(attachBaseComplete)
        unDispatchTask.add(onCreateComplete)
        unDispatchTask.add(appOnCreateStart)
    }

    private fun initDepend() {
        allCustomTask.forEach { task ->
            genEarliestDepend(task, task.getEarliestPeriod())
            genLatestDepend(task, task.getLatestPeriod())
            genCommonDepend(task)
        }
        addDepend(superAttachBase, appAttachBaseStart)
        addDepend(attachBaseComplete, superAttachBase)
        addDepend(appOnCreateStart, attachBaseComplete)
        addDepend(superOnCreate, appOnCreateStart)
        addDepend(onCreateComplete, superOnCreate)
    }

    private fun initReadyQueue() {
        readyQueue.clear()
        val readyTasks = mutableListOf<ILaunchTask>()
        for ((task, extra) in taskExtra) {
            val dependent = extra.dependent
            if (!dependent.isEmpty()) continue  // 有依赖的任务
            readyTasks.add(task)    //没有依赖,Task可以随时被执行
            addReadyTask(task, getPriority(task))
        }
        for (task in readyTasks) unDispatchTask.remove(task)
    }

    private fun addReadyTask(task: ILaunchTask, priority: Int) {
        val queue = if (task.runInMainThread()) uiReadyQueue else readyQueue
        queue.add(PriorityLaunchTask(task, priority))
    }
}

class PriorityLaunchTask(val task: ILaunchTask, private val priority: Int) :
    Comparable<PriorityLaunchTask> {
    override fun compareTo(other: PriorityLaunchTask) = -(this.priority - other.priority)
}