一、我們會遇到一種情況:
1、點擊某個按鈕或發生某個信息指令,進而執行一個任務(如請求接口)
2、但是!由於快速點擊,或發生信息指令時、短時間內頻繁執行了多次
3、當我們收到某個信息指令時,只需執行一次任務時,代碼邏輯顯得更加雜亂
因此,本文加入了方法體任務隊列概念,不多說,直接上源碼!!
二、方法隊列源碼,FunQueueTask
/**
* 方法體任務隊列
* 注:
* offer() :如果BlockingQueue可以容納,則返回true,否則返回false.(本方法不阻塞當前執行方法的線程)
* poll() :若隊列爲空,返回null(本方法不阻塞當前執行方法的線程)
* peek() :取出隊頭的元素,並不刪除
*
* 1、produceChain與consumeChain需要成對出現
* 2、produceSingle與consumeSingle需要成對出現
*
*/
class FunQueueTask<T> {
//鏈式任務隊列
private var chainBasket: BlockingQueue<() -> T?> = LinkedBlockingQueue()
//鏈式任務隊列標記位
private var flag = true
//單任務隊列
private var singleBasket: BlockingQueue<() -> T?> = LinkedBlockingQueue(1)
//******************************鏈式隊列*************************************************
fun produceChain(block: () -> T?): Boolean {
val isSucceed = chainBasket.offer(block)
YLogUtils.d("鏈式任務--生產", block, "成功?", isSucceed)
//如果隊列只有一個元素,則立馬出列
if (flag && isSucceed) {
flag = false
val t = chainBasket.poll()
YLogUtils.d("鏈式任務--隊列只有一個元素,立馬消費", t)
t?.invoke()
}
return isSucceed
}
fun consumeChain() {
val t = chainBasket.poll()
YLogUtils.d("鏈式任務--消費", t)
t?.invoke()
//若方法體隊列已全部出列,則標記爲true
if (t == null) {
flag = true
}
}
//*******************************單任務隊列*************************************************
fun produceSingle(block: () -> T?): Boolean {
val isSucceed = singleBasket.offer(block)
YLogUtils.d("單任務--生產", block, "成功?", isSucceed)
//如果隊列有元素,則立馬取出,但不消費
if (isSucceed) {
val t = singleBasket.peek()
YLogUtils.d("單任務--隊列有元素,取出元素,但不消費", t)
t?.invoke()
}
return isSucceed
}
fun consumeSingle() {
val t = singleBasket.poll()
YLogUtils.d("單任務-消費", t)
}
}
三、FunTaskManager,全局管理任務隊列,也可以局部創建FunQueueTask
/**
* 任務經營者(單例,全局任務)
*/
class FunTaskManager private constructor() {
//方法體任務隊列
private val funQueueTask = FunQueueTask<Any>()
fun getFunQueueTask(): FunQueueTask<Any> {
return funQueueTask
}
private object Holder {
val instance = FunTaskManager()
}
companion object {
@Synchronized
fun getInstance(): FunTaskManager {
return Holder.instance
}
}
}
四、simple
/**
* @Author Administrator
* @Date 2020/3/12-11:38
* @TODO mvc 任務隊列請求
*/
class QueueApiSimpleActivity : BaseActivity() {
companion object {
fun startAct(context: Context) {
ActivityUtils.startActivity(context, QueueApiSimpleActivity::class.java)
}
}
private val simpleMode = ApiSimpleModel()
override fun initLayoutID(): Int = R.layout.simple_api_test_activity_queue
override fun initUI(savedInstanceState: Bundle?) {
}
fun onRequest(view: View) {
when (view.id) {
R.id.requestData_common -> {
for (i in 1..10) {
sendGiftCommon(SendGiftVo("123", "456", 1, 100, 0))
}
}
R.id.requestData_fun_single -> {
for (i in 1..10) {
FunTaskManager.getInstance().getFunQueueTask().produceSingle {
sendGiftFunSingle(SendGiftVo("123", "456", 1, 100, 0))
}
}
}
R.id.requestData_fun_chain -> {
for (i in 1..10) {
FunTaskManager.getInstance().getFunQueueTask().produceChain {
sendGiftFunChain(SendGiftVo("123", "456", 1, 100, 0))
}
}
}
}
}
/**
* 普通請求
*/
private fun sendGiftCommon(sendGiftVo: SendGiftVo) {
simpleMode.sendGift(RxObserver(doNext = { it ->
tv_msg.setText(it.msg)
}, doError = { _, _ ->
}), lifecycleProvider, sendGiftVo)
}
/**
* 單任務隊列
*/
private fun sendGiftFunSingle(sendGiftVo: SendGiftVo) {
simpleMode.sendGift(RxObserver(doNext = { it ->
tv_msg.setText(it.msg)
FunTaskManager.getInstance().getFunQueueTask().consumeSingle()
}, doError = { _, _ ->
FunTaskManager.getInstance().getFunQueueTask().consumeSingle()
}), lifecycleProvider, sendGiftVo)
}
/**
* 鏈式隊列
*/
private fun sendGiftFunChain(sendGiftVo: SendGiftVo) {
simpleMode.sendGift(RxObserver(doNext = { it ->
tv_msg.setText(it.msg)
FunTaskManager.getInstance().getFunQueueTask().consumeChain()
}, doError = { _, _ ->
FunTaskManager.getInstance().getFunQueueTask().consumeChain()
}), lifecycleProvider, sendGiftVo)
}
}
五、測試結果
5.1、普通請求結果
- 提交多次請求任務,交由網絡框架的線程池隊列逐一執行任務
5.2.單任務隊列
- 提交多次請求任務,若任務已存在,未出列,則只執行一次任務
5.3、鏈式隊列
- 提交多次請求任務,每次只執行一個任務,執行完當前任務後,再執行下一個任務,直到所有任務出列
github地址 YLibrary