一、概述

QTaskManager是一个对抽象任务进行调度、分配及管理的简化管理框架,支持并行执行任务、顺序执行任务、按时执行任务、串行执行任务等基本任务操作。
NOTICE:框架是基于Android开发的,但稍加修改可以直接在Java程序中使用(与Android的耦合主要集中在主线程运行部分)。
在框架内,任务被抽象为一个泛型,框架不负责任务的执行细节,只要求调用方提供任务执行能力,并在任务执行开始和结束时通知任务状态即可。
使用QTaskManager做简单的任务调度管理,可以帮我们解决一些比较棘手的细节问题,比如:

  1. 假设有两个接口请求A和B,都会改变本地的数据缓存,要想保证数据缓存不随接口的返回顺序得到不同的结果,我们需要控制两个接口请求的时机,A执行完成后B再执行,或者B执行后A再执行。这时我们需要一个控制器,控制A/B谁先来谁先执行。
  2. 再细化一个场景,接口A执行时,接口B在等待A执行,此时用户再次触发了一个接口B的的操作,我们需要取消之前等待执行的接口B的执行。
  3. 或者,我们需要在300ms后执行接口A,在接口A执行完成后执行接口B,等等……
    类似的需求数不胜数,其实抽象来看就是一个简单的任务调度问题,分别是任务A/B的串联执行、并行执行和按时间规划执行。

QTaskManager就是对执行策略的抽象,支持的就是以上几种执行方式。下面我们来看下,这个框架的架构方式与接口。

二、QTaskManager的类设计


- TaskExecutorFactory:框架的对外工厂,可以生成三种任务执行器,分别为:

  1. 默认的任务执行器(createDefaultTaskExecutor):支持顺序执行、串行执行和按时执行任务;
  2. 顺序任务执行器(createSequenceTaskExecutor):对所有添加的任务,按添加时指定的顺序执行,不论任务是不是定时任务,或者指定了某个任务必须在另一个任务完成之后执行,只要使用此执行器,所有的任务都顺序执行;
  3. 串行任务处理器(createSerialTaskExecutor):对所有添加的任务,按添加时指定的顺序一个接着一个执行,同样的,不论任务是不是定时任务,只要使用此执行器,所有的任务都串行执行;
  • ITaskExecutor:框架最终创建出来的任务执行器,在任务执行的过程中,我们对此接口进行操作,包括任务执行的配置,开始/结束任务执行,添加/删除任务等。
  • ITaskComparator:用于比较两个任务是否相同,由框架外提供此能力。
  • ITaskExecutorAbility:指定如何真正执行任务,框架外实现。
  • AbsTaskExecutor:抽象的任务执行器,具有三个子类实现,分别对于默认任务执行器、顺序任务执行器、串行任务执行器。
  • ITaskManager:完成任务添加/删除等操作。
  • ITaskPool:所有待执行任务形成的任务池的抽象接口,最终实现为TaskPoolImpl。

三、使用方式

1. 根据需要生成并配置一个任务执行器

ITaskExecutor<ExecuteTask> mDefaultTaskExecutor = TaskExecutorFactory.createDefaultTaskExecutor();
  • 1

对生成的任务执行器,我们需要做一些简单的配置:

//设置发现任务重复时的处理策略
mDefaultTaskExecutor.setDuplicateTaskStrategy(DuplicateTaskStrategy.KEEP_CURRENT);
//设置任务是否在主线程执行
mDefaultTaskExecutor.setRunOnUIThread(false);
//设置辅助框架完成任务执行的能力
mDefaultTaskExecutor.setTaskExecutorAbility(taskExecutorSequent);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • setDuplicateTaskStrategy用来指定当发现相同任务时应该执行的操作,有三种操作方式:两者皆保留KEEP_ALL、保持已经添加的任务KEEP_PREVIOUS、更新任务KEEP_CURRENT(删除之前的任务)。
  • setRunOnUIThread用来指定任务执行器内的任务在主线程还是子线程执行。
  • setTaskExecutorAbility用来配置需要框架实现的能力,包括两点:比较任务是否相同以及正在执行任务。示例如下:
ITaskExecutorAbility<ExecuteTask> mTaskExecutorAbilitySequent = new ITaskExecutorAbility<ExecuteTask>() {@Overridepublic boolean isSame(ExecuteTask taskLeft, ExecuteTask tastRight) {return taskLeft.id == tastRight.id;}@Overridepublic void executeTask(ExecuteTask task) {task.run();}};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2. 启动/终止任务执行器

上面我们指定好了任务执行器的任务存储策略和任务执行方式,接下来我们就可以启动/终止任务执行器了:

mDefaultTaskExecutor.startExecute();
mDefaultTaskExecutor.stopExecute();
  • 1
  • 2

任务执行器可以不断的被开始/停止,但是建议这两个操作只执行一次。

3. 添加/删除任务

任务执行器被启动后,并不会执行任务,因为我们并没有添加任何任务到执行器内,这时候我们需要借助ITaskManager接口添加/删除任务:

//获取TaskManager
ITaskManager<ExecuteTask> mTaskManager = mDefaultTaskExecutorHelper.getTaskManager();//向任务执行器内添加一个待执行任务
mTaskManager.addTask(new ExecuteTask(id));//向任务执行器内添加一个在300ms后执行的任务(定时任务)
mTaskManager.addTaskDelayed(new ExecuteTask(id), 300);//向任务执行器内已存在的任务anchorId前面添加一个任务,此任务先于anchorId任务执行
mTaskManager.addTaskBeforeAnchor(new ExecuteTask(id), new ExecuteTask(anchorId));//向任务执行器内已存在的任务anchorId后面添加一个任务,此任务后于anchorId任务执行
mTaskManager.addTaskAfterAnchor(new ExecuteTask(id), new ExecuteTask(anchorId));//向任务执行器内已存在的任务anchorId后面添加一个任务,此任务后于anchorId任务执行,
//第三个参数true表示此任务等待其anchor任务执行完成后才能执行,
//所以如果是默认任务执行器,此任务会在anchorId执行完成后才会执行,但如果是顺序任务执行器,则忽略此规则
mTaskManager.addTaskAfterAnchor(new ExecuteTask(id), new ExecuteTask(anchorId), true);//从任务执行器内删除任务id为anchorId的执行任务
mTaskManager.removeTask(new ExecuteTask(anchorId));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

上面就是框架支持的几种任务添加/删除策略,这些情况基本覆盖了我们常用的任务调度策略(顺序、串行和定时执行)。

4. 任务执行状态通知

对于串行任务执行器或默认的任务执行器,我们需要通知任务执行开始完成事件,来帮助框架执行下一个任务。
其中串行任务执行器是必须通知的,而默认任务执行器则非必须,此通知仅对调用接口addTaskAfterAnchor(T task, T anchorTask, true)的任务task有效,因为任务task需要在anchorTask执行完成后执行。

mSerialTaskExecutor.notifyTaskBegin(mCurrentTask);
mSerialTaskExecutor.notifyTaskFinish(mCurrentTask);
  • 1
  • 2

好了,经过以上几步集成,一个简单的任务执行器就启动并开始工作了。但是前文中我们说好了的支持并行任务处理呢?我们上面只提供了顺序执行、定时执行和串行执行三种执行方式,并行任务执行怎么实现?

5. 并行任务处理

实现并行任务处理其实并不难,我们要借助的是框架外执行任务处理的接口来实现。那么为什么框架内不直接实现并行任务处理呢?我的考虑是:并行处理任务需要开很多线程,这就要设计线程池管理策略,如果框架实现,无法灵活地设置线程池管理策略,所以还是交给外面算了。
下面我们来看下一个简单的无线程池管理的并行任务处理实现:

ITaskExecutorAbility<ExecuteTask> taskExecutorParallel = new ITaskExecutorAbility<ExecuteTask>() {@Overridepublic boolean isSame(ExecuteTask existedTask, ExecuteTask newAddTask) {return existedTask.id == newAddTask.id;}@Overridepublic void executeTask(final ExecuteTask task) {new Thread(new Runnable() {@Overridepublic void run() {task.run();}}).start();}};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

是的,就这么简单,在框架对外通知要执行任务时,给任务执行包装一个线程即可。当然复杂的做法不是这样的,否则每个任务一个线程应用直接就卡死了,一般做法封装一个线程池,由线程池来执行task。

四、总结

QTaskManager任务管理框架的设计与使用的讲解就此结束了,框架支持顺序执行、串行执行和按时执行抽象任务,支持配置子线程和主线程内执行任务,支持任务的重复时的处理策略等,基本上能满足简单的任务管理需求了。
欢迎大家去看看代码,地址:https://github.com/qqliu10u/QTaskManager。
功能刚刚完成,应该还不太成熟,如有缺陷,请不吝指出,Thanks。

Android抽象任务管理框架QTaskManager及其使用方式介绍相关推荐

  1. 【Android】播放音频的几种方式介绍

    转自:u013366008的博客  https://blog.csdn.net/u013366008/article/details/76577372 Android中播放音乐的几种方式 前言 前几天 ...

  2. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  3. 超越Android:Kotlin在后端的工作方式

    by Adam Arold 亚当·阿罗德(Adam Arold) 超越Android:Kotlin在后端的工作方式 (Going Beyond Android: how Kotlin works on ...

  4. [转]Android中程序与Service交互的方式——交互方式

    本文转自:http://blog.csdn.net/yihongyuelan/article/details/7216188 上一篇文章:Android中程序与Service交互的方式--综述 简述了 ...

  5. android 定位的几种方式介绍

    [地理位置] android 定位的几种方式介绍 开发中对于地图及地理位置的定位是我们经常要用地,地图功能的使用使得我们应用功能更加完善,下面 www.androidkaifa.com 总结了一下网络 ...

  6. android tabpageindicator 参数,Android实现Tab布局的4种方式(Fragment+TabPageIndicator+ViewPager)...

    Android现在实现Tab类型的界面方式越来越多,今天就把常见的实现方式给大家来个总结.目前写了: 1.传统的ViewPager实现 2.FragmentManager+Fragment实现 3.V ...

  7. android中资源文件的两种访问方式,在android开发中进行数据存储与访问的多种方式介绍...

    在android开发中进行数据存储与访问的多种方式介绍 更新时间:2013年06月07日 16:24:23   作者: 很多时候我们的软件需要对处理后的数据进行存储或再次访问,Android为数据存储 ...

  8. Android中的5种数据存储方式

    Android中的5种数据存储方式 Android中的5种数据存储方式 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPref ...

  9. android xpath解析xml,Android 中处理 XML 的四种方式-DOM

    Android 中处理 XML 的几种方式连载中,我们就不介绍合成 XML 了,因为合成 XML 可以直接拼接字符串,虽然看起很不高大上,但却很有效.我们主要介绍如何取 XML 中的值. 适用 DOM ...

最新文章

  1. node 跨域请求设置
  2. 利用百度api判断已知经纬度的一个点是否在多边形内
  3. 2013长春区域赛总结
  4. 高级Blazor:从Edge共享程序集和调试
  5. DPDK初始化分析(一)
  6. gradle 区分系统_Android 学习记录_系统结构, res 目录, App 目录下的 build.gradle 文件...
  7. VirtualBox安装VBoxGuestAdditions增强功能
  8. 最新!Photoshop 2022 (ps2022)中文
  9. 真实如刀的洞见:和扶墙老师聊技术、组织和商业
  10. 音视频入门:H264、H265概念总结
  11. Mac Navicat连接MySQL8.0.11出错:2003 - Can't connect to MySQL server on ……(61 Connection refused)
  12. 如何打开.pdm文件(Mac OS X)
  13. 戴维解惑——用iTestin云测做测试怎样拿大奖
  14. Android 手机听筒Earpiece和扬声器speaker切换
  15. 技术博客1鸿蒙系统和安卓的区别有哪些
  16. 使用键盘移动鼠标指针
  17. 华为nova8pro和小米11哪个好
  18. 超高频RFID涉密资产智能档案柜应用
  19. hive | 解决character '​' not supported here
  20. 快速对帝国竞争算法ICA的了解

热门文章

  1. QXRService:基于高通QXRService获取SLAM Camera图像
  2. Java控制鼠标和键盘的方法
  3. 3D建模zbrush笔刷分享
  4. 故宫景点功课24:宁寿宫区6
  5. 微信小程序开发(4)--发布评论
  6. Modelsim设置默认窗口排版
  7. Android RecyclerView万能分割线
  8. java 拼html页面返回,java返回html标签
  9. EXCEL-VBA:EXCEL的各种文件名获取
  10. 【欣赏】一组唯美的图片