手动实现kt(java)同步工作流和异步工作流
生活随笔
收集整理的這篇文章主要介紹了
手动实现kt(java)同步工作流和异步工作流
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前言
項(xiàng)目開(kāi)發(fā)中可能會(huì)出現(xiàn)需要多個(gè)同步任務(wù)串行執(zhí)行,或者多個(gè)異步任務(wù)都執(zhí)行完畢再執(zhí)行下一步的
其實(shí)如果用kotlin的協(xié)程的話,可以很方便的完成,但如果不想用kt寫(xiě)或者引入?yún)f(xié)程庫(kù)的話,就可以用下面兩個(gè)工具類(lèi)
正文
同步串行執(zhí)行任務(wù),使用鏈表結(jié)構(gòu)
import com.lt.androidkj.utils.mlistener.EmptyListener import com.lt.androidkj.utils.mlistener.FunctionFlowBeanListener/*** creator: lt 2019/11/26--10:40 lt.dygzs@qq.com* effect : 方法順序運(yùn)作工具類(lèi),使用鏈表數(shù)據(jù)結(jié)構(gòu)* warning:*/ class FunctionFlow {private var first: LinkedBean? = null//頭結(jié)點(diǎn)private var last: LinkedBean? = null//尾結(jié)點(diǎn)private var finishListener: EmptyListener? = null//全部事件結(jié)束的回調(diào)/*** 順序的添加任務(wù)* @param id 正常情況下沒(méi)什么用,但是next(n)的時(shí)候跳轉(zhuǎn)到指定的id上* @param function 執(zhí)行的任務(wù),回調(diào)里有個(gè)FunctionFlowBean類(lèi)型的參數(shù),調(diào)用他的invoke()可以執(zhí)行后面的方法*/fun add(id: Int = 0, function: FunctionFlowBeanListener): FunctionFlow {//第一次添加if (first == null) {first = LinkedBean(function, id)last = firstreturn this}//以后再添加val functionFlowBean = LinkedBean(function, id)last!!.next = functionFlowBeanlast = functionFlowBeanreturn this}/*** 開(kāi)始順序執(zhí)行所有任務(wù),后面的任務(wù)完成后調(diào)用.invoke()即可開(kāi)始下一個(gè)任務(wù)* @param finishListener 全部任務(wù)完成后觸發(fā),可以不傳*/@JvmOverloadsfun start(finishListener: EmptyListener? = null) {val first = first ?: returnthis.finishListener = finishListener//設(shè)置尾結(jié)點(diǎn),保證鏈?zhǔn)秸{(diào)用中,參數(shù)不為空val noFunctionFlowBean = LinkedBean({}, -1)last!!.next = noFunctionFlowBeanlast = noFunctionFlowBean//開(kāi)始第一個(gè)任務(wù)first.function(first.next!!)}/*** 鏈表bean*/inner class LinkedBean(val function: FunctionFlowBeanListener,val id: Int,var next: LinkedBean? = null) {/*** 開(kāi)始下一個(gè)任務(wù)* @param skip -1表示下一個(gè)任務(wù),大于0表示跳到id為n的任務(wù)*/@JvmOverloadsfun ok(skip: Int = -1) {if (skip < 0) {//執(zhí)行下一個(gè)任務(wù)val next = nextif (next == null) {finishListener?.invoke()return}function(next)} else {//跳到id為n的任務(wù)var next: LinkedBean? = thiswhile (true) {if (next == null) {//判斷如果后續(xù)沒(méi)有方法,則走finishfinishListener?.invoke()return}if (next.id == skip) {//如果下一個(gè)任務(wù)的id和指定的id相同,則調(diào)用下一個(gè)方法next.function(next.next!!)return}next = next.next//如果上面兩個(gè)條件都不符合,則判斷下一個(gè)任務(wù)}}}} }typealias EmptyListener = () -> Unit typealias FunctionFlowBeanListener = (FunctionFlow.LinkedBean) -> Unit typealias FunctionStartsBeanListener = (FunctionStarts.EndBean) -> Unit使用方式:
異步并行執(zhí)行任務(wù),也是使用的鏈表結(jié)構(gòu):
import com.lt.androidkj.utils.ThreadPool.ThreadType.* import com.lt.androidkj.utils.mlistener.EmptyListener import com.lt.androidkj.utils.mlistener.FunctionStartsBeanListener/*** creator: lt 2019/12/23--17:15 lt.dygzs@qq.com* effect : 同時(shí)執(zhí)行所有任務(wù),全部執(zhí)行完成后調(diào)用完成的回調(diào),可以指定線程,默認(rèn)子線程* warning:*/ class FunctionStarts {private val map = LinkedHashMap<EndBean, ThreadPool.ThreadType>()/*** 添加任務(wù),并指定該任務(wù)所運(yùn)行的線程模式*/fun add(type: ThreadPool.ThreadType = CACHE, function: FunctionStartsBeanListener): FunctionStarts {map[EndBean(function)] = typereturn this}/*** 開(kāi)始所有任務(wù),并在全部完成后執(zhí)行回調(diào),且不保證運(yùn)行在哪個(gè)線程中*/fun start(finishListener: EmptyListener) {map.forEach { (bean, type) ->when (type) {SINGLE -> ThreadPool::submitToSingleThreadPoolCACHE -> ThreadPool::submitToCacheThreadPoolFIXED -> ThreadPool::submitToTimeThreadPoolNoTimeMAIN -> ::post}{bean.endListener = {synchronized(this@FunctionStarts) {map.remove(bean)if (map.size == 0)finishListener()}}bean.run(bean)}}}/*** 調(diào)用該類(lèi)的end方法,表示任務(wù)已經(jīng)執(zhí)行完畢* @param run 提交的任務(wù)*/class EndBean(val run: FunctionStartsBeanListener) {//任務(wù)結(jié)束的回調(diào)var endListener: EmptyListener? = null/*** 表示任務(wù)已經(jīng)執(zhí)行完畢*/fun ok() {endListener?.invoke()}} }/*** 線程類(lèi)型*/enum class ThreadType {/*** 單例線程,選擇這種方式會(huì)按照啟動(dòng)的先后順序串行執(zhí)行*/SINGLE,/*** 緩存線程池,選擇這種方式會(huì)和其他任務(wù)并行執(zhí)行,且無(wú)上限*/CACHE,/*** 固定長(zhǎng)度的線程池,達(dá)到設(shè)定的線程數(shù)量后,后面的任務(wù)等待空閑線程執(zhí)行完畢后再執(zhí)行*/FIXED,/*** 跑在主線程中*/MAIN} ::post實(shí)現(xiàn)方式如下val handler=Handler()fun post(listener:EmptyListener){handler.post(listener)}其他的submitXXX都是提交到線程池,類(lèi)似于如下 val singleThreadExecutor = Executors.newSingleThreadExecutor()//可以自己搜索如何創(chuàng)建或自定義線程池fun submitToSingleThreadPool(runnable: EmptyListener): Future<*> =singleThreadExecutor.submit(runnable)使用方式:
而且還能聯(lián)合使用來(lái)應(yīng)對(duì)復(fù)雜需求,比如
先按照順序彈兩個(gè)彈窗(關(guān)閉前一個(gè)在打開(kāi)下面的),然后請(qǐng)求三個(gè)異步接口(但要求第二個(gè)和第三個(gè)要按順序執(zhí)行),接口全部成功后在按照順序彈兩個(gè)彈窗
FunctionFlow().add {showSelectPhotoDialog(1) { arr ->it.ok()}}.add {showSelectPhotoDialog(1) { arr ->it.ok()}}.add {//執(zhí)行異步網(wǎng)絡(luò)請(qǐng)求FunctionStarts().add {http1 {it.ok()}}.add(ThreadPool.ThreadType.SINGLE) {http2 {it.ok()}}.add(ThreadPool.ThreadType.SINGLE) {http3 {it.ok()}}.start {print("異步接口執(zhí)行完畢")it.ok()}}.add {showSelectPhotoDialog(1) { arr ->it.ok()}}.add {showSelectPhotoDialog(1) { arr ->it.ok()}}.start {print("任務(wù)全部執(zhí)行完成")}總結(jié)
以上是生活随笔為你收集整理的手动实现kt(java)同步工作流和异步工作流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 写一个测试工具类,只在debug时运行,
- 下一篇: 数据结构特性解析 (二) ArrayLi